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:

Previous
From: "John Sidney-Woollett"
Date:
Subject: Re: Replication
Next
From: Melanie Bergeron
Date:
Subject: automatic verifications