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;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to