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: