Re: functions returning sets - Mailing list pgsql-general
| From | Joe Conway |
|---|---|
| Subject | Re: functions returning sets |
| Date | |
| Msg-id | 3FE21ECB.1030102@joeconway.com Whole thread Raw |
| In response to | Re: functions returning sets (Joe Conway <mail@joeconway.com>) |
| Responses |
Re: functions returning sets
|
| List | pgsql-general |
Joe Conway wrote:
> Tom Lane wrote:
>> We still need a code addition that uses an ExprState shutdown callback
>> to reset the state of an SRF that uses the SRF_XXX macros. Joe, have
>> you had time to give that any thought?
>
> Yeah, I've gotten something started, but couldn't do much without the
> shutdown getting called. I hadn't yet figured out the best way to make
> that happen, so I'm glad you did ;-). I'll update to cvs tip and try
> Jeff's function with my changes and your committed changes. Will get
> back shortly with the results.
OK, updated to cvs tip, and with the attached patch applied, all seems well:
regression=# select id from foo where 'a' in (select
pgxml_xpath(doc,'/top/node'));
id
----
1
2
3
(3 rows)
Any comment on the patch?
BTW, I am seeing:
[...]
test portals_p2 ... ok
test rules ... FAILED
test foreign_key ... ok
[...]
but it seems unrelated to this change -- caused by a redefinition of the
pg_stats view. I guess I need to initdb.
Thanks,
Joe
Index: src/backend/utils/fmgr/funcapi.c
===================================================================
RCS file: /opt/src/cvs/pgsql-server/src/backend/utils/fmgr/funcapi.c,v
retrieving revision 1.12
diff -c -r1.12 funcapi.c
*** src/backend/utils/fmgr/funcapi.c 29 Nov 2003 19:52:01 -0000 1.12
--- src/backend/utils/fmgr/funcapi.c 18 Dec 2003 01:51:37 -0000
***************
*** 17,23 ****
#include "catalog/pg_type.h"
#include "utils/syscache.h"
-
/*
* init_MultiFuncCall
* Create an empty FuncCallContext data structure
--- 17,22 ----
***************
*** 58,63 ****
--- 57,64 ----
retval->user_fctx = NULL;
retval->attinmeta = NULL;
retval->multi_call_memory_ctx = fcinfo->flinfo->fn_mcxt;
+ retval->flinfo = fcinfo->flinfo;
+ retval->shutdown_reg = false;
/*
* save the pointer for cross-call use
***************
*** 106,115 ****
* Clean up after init_MultiFuncCall
*/
void
! end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
{
/* unbind from fcinfo */
! fcinfo->flinfo->fn_extra = NULL;
/*
* Caller is responsible to free up memory for individual struct
--- 107,119 ----
* Clean up after init_MultiFuncCall
*/
void
! end_MultiFuncCall(Datum arg)
{
+ FuncCallContext *funcctx = (FuncCallContext *) DatumGetPointer(arg);
+ FmgrInfo *flinfo = funcctx->flinfo;
+
/* unbind from fcinfo */
! flinfo->fn_extra = NULL;
/*
* Caller is responsible to free up memory for individual struct
Index: src/include/funcapi.h
===================================================================
RCS file: /opt/src/cvs/pgsql-server/src/include/funcapi.h,v
retrieving revision 1.10
diff -c -r1.10 funcapi.h
*** src/include/funcapi.h 29 Nov 2003 22:40:53 -0000 1.10
--- src/include/funcapi.h 18 Dec 2003 20:17:07 -0000
***************
*** 111,116 ****
--- 111,126 ----
*/
MemoryContext multi_call_memory_ctx;
+ /*
+ * pointer to FmgrInfo needed for shutdown
+ */
+ FmgrInfo *flinfo;
+
+ /*
+ * true if registered shutdown callback
+ */
+ bool shutdown_reg;
+
} FuncCallContext;
/*----------
***************
*** 203,209 ****
/* from funcapi.c */
extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
! extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
#define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
--- 213,219 ----
/* from funcapi.c */
extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
! extern void end_MultiFuncCall(Datum arg);
#define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
***************
*** 217,231 ****
(_funcctx)->call_cntr++; \
rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
rsi->isDone = ExprMultipleResult; \
PG_RETURN_DATUM(_result); \
} while (0)
#define SRF_RETURN_DONE(_funcctx) \
do { \
ReturnSetInfo *rsi; \
! end_MultiFuncCall(fcinfo, _funcctx); \
rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
rsi->isDone = ExprEndResult; \
PG_RETURN_NULL(); \
} while (0)
--- 227,252 ----
(_funcctx)->call_cntr++; \
rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
rsi->isDone = ExprMultipleResult; \
+ if (!_funcctx->shutdown_reg) \
+ { \
+ RegisterExprContextCallback(rsi->econtext, \
+ end_MultiFuncCall, \
+ PointerGetDatum(_funcctx)); \
+ _funcctx->shutdown_reg = true; \
+ } \
PG_RETURN_DATUM(_result); \
} while (0)
#define SRF_RETURN_DONE(_funcctx) \
do { \
ReturnSetInfo *rsi; \
! end_MultiFuncCall(PointerGetDatum(_funcctx)); \
rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
rsi->isDone = ExprEndResult; \
+ UnregisterExprContextCallback(rsi->econtext, \
+ end_MultiFuncCall, \
+ PointerGetDatum(_funcctx)); \
+ _funcctx->shutdown_reg = false; \
PG_RETURN_NULL(); \
} while (0)
pgsql-general by date: