Re: [PATCHES] libpq events patch (with sgml docs) - Mailing list pgsql-hackers

From Andrew Chernow
Subject Re: [PATCHES] libpq events patch (with sgml docs)
Date
Msg-id 48D0E0E8.5070301@esilo.com
Whole thread Raw
In response to Re: [PATCHES] libpq events patch (with sgml docs)  (Andrew Chernow <ac@esilo.com>)
List pgsql-hackers
Andrew Chernow wrote:
>  > Now, it's questionable how tense we need to be about that as long as
>  > event proc failure aborts calling of later event procs.  That means
>  > that procs have to be robust against getting DESTROY with no CREATE
>  > calls in any case.  Should we try to make that less uncertain?
>  >
>  >
>
> I attached a patch that adds a 'needDestroy' member to PGEvent  It is
> set when resultcreate or resultcopy succeeds and checked during a
> PQclear.  That *should* resolve the issue of "no resultcreate but gets a
> resultdestroy".
>
>

Shoot.  I have a booboo in that last patch.  Attached is the corrected version.

--
Andrew Chernow
eSilo, LLC
every bit counts
http://www.esilo.com/
Index: src/interfaces/libpq/fe-exec.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v
retrieving revision 1.198
diff -C6 -r1.198 fe-exec.c
*** src/interfaces/libpq/fe-exec.c    17 Sep 2008 04:31:08 -0000    1.198
--- src/interfaces/libpq/fe-exec.c    17 Sep 2008 10:49:10 -0000
***************
*** 356,367 ****
--- 356,369 ----
          if (!dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
                                    dest->events[i].passThrough))
          {
              PQclear(dest);
              return NULL;
          }
+
+         dest->events[i].needDestroy = TRUE;
      }

      return dest;
  }

  /*
***************
*** 378,396 ****
          return NULL;

      newEvents = (PGEvent *) malloc(count * sizeof(PGEvent));
      if (!newEvents)
          return NULL;

-     memcpy(newEvents, events, count * sizeof(PGEvent));
-
-     /* NULL out the data pointers and deep copy names */
      for (i = 0; i < count; i++)
      {
          newEvents[i].data = NULL;
!         newEvents[i].name = strdup(newEvents[i].name);
          if (!newEvents[i].name)
          {
              while (--i >= 0)
                  free(newEvents[i].name);
              free(newEvents);
              return NULL;
--- 380,398 ----
          return NULL;

      newEvents = (PGEvent *) malloc(count * sizeof(PGEvent));
      if (!newEvents)
          return NULL;

      for (i = 0; i < count; i++)
      {
+         newEvents[i].proc = events[i].proc;
+         newEvents[i].passThrough = events[i].passThrough;
+         newEvents[i].needDestroy = FALSE;
          newEvents[i].data = NULL;
!         newEvents[i].name = strdup(events[i].name);
          if (!newEvents[i].name)
          {
              while (--i >= 0)
                  free(newEvents[i].name);
              free(newEvents);
              return NULL;
***************
*** 663,679 ****

      if (!res)
          return;

      for (i = 0; i < res->nEvents; i++)
      {
!         PGEventResultDestroy evt;

-         evt.result = res;
-         (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt,
-                                    res->events[i].passThrough);
          free(res->events[i].name);
      }

      if (res->events)
          free(res->events);

--- 665,685 ----

      if (!res)
          return;

      for (i = 0; i < res->nEvents; i++)
      {
!         if(res->events[i].needDestroy)
!         {
!             PGEventResultDestroy evt;
!
!             evt.result = res;
!             (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt,
!                                        res->events[i].passThrough);
!         }

          free(res->events[i].name);
      }

      if (res->events)
          free(res->events);

***************
*** 1609,1620 ****
--- 1615,1628 ----
                                    libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
                                    res->events[i].name);
                  pqSetResultError(res, conn->errorMessage.data);
                  res->resultStatus = PGRES_FATAL_ERROR;
                  break;
              }
+
+             res->events[i].needDestroy = TRUE;
          }
      }

      return res;
  }

Index: src/interfaces/libpq/libpq-int.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/libpq-int.h,v
retrieving revision 1.132
diff -C6 -r1.132 libpq-int.h
*** src/interfaces/libpq/libpq-int.h    17 Sep 2008 04:31:08 -0000    1.132
--- src/interfaces/libpq/libpq-int.h    17 Sep 2008 10:49:10 -0000
***************
*** 153,164 ****
--- 153,165 ----
  typedef struct PGEvent
  {
      PGEventProc    proc;            /* the function to call on events */
      char       *name;            /* used only for error messages */
      void       *passThrough;    /* pointer supplied at registration time */
      void       *data;            /* optional state (instance) data */
+     int           needDestroy;     /* indicates a PGEVT_RESULTDESTROY is needed. */
  } PGEvent;

  struct pg_result
  {
      int            ntups;
      int            numAttributes;

pgsql-hackers by date:

Previous
From: Andrew Chernow
Date:
Subject: Re: [PATCHES] libpq events patch (with sgml docs)
Next
From: "Robert Haas"
Date:
Subject: Re: Common Table Expressions (WITH RECURSIVE) patch