PG_COPYRES_EVENTS specifies copying the source
result's events. (But any instance data associated with the source
is not copied.)
+ The event procedures receive PGEVT_RESULTCOPY events.
,
,
and
- <function>PQsetResultInstanceData> functions. Note that
+ <xref linkend="libpq-PQresultSetInstanceData"/> functions. Note that
unlike the pass-through pointer, instance data of a PGconn
is not automatically inherited by PGresults created from
it.
libpq does not know what pass-through
is called. It is the ideal time to initialize any
instanceData an event procedure may need. Only one
register event will be fired per event handler per connection. If the
- event procedure fails, the registration is aborted.
+ event procedure fails (returns zero), the registration is cancelled.
typedef struct
conn is the connection used to generate the
result. This is the ideal place to initialize any
instanceData that needs to be associated with the
- result. If the event procedure fails, the result will be cleared and
- the failure will be propagated. The event procedure must not try to
- the result object for itself. When returning a
- failure code, all cleanup must be performed as no
- PGEVT_RESULTDESTROY event will be sent.
+ result. If an event procedure fails (returns zero), that event
+ procedure will be ignored for the remaining lifetime of the result;
+ that is, it will not receive PGEVT_RESULTCOPY
+ or PGEVT_RESULTDESTROY events for this result or
+ results copied from it.
src result is what was copied while the
dest result is the copy destination. This event
can be used to provide a deep copy of instanceData,
- since PQcopyResult cannot do that. If the event
- procedure fails, the entire copy operation will fail and the
-
dest result will be cleared. When returning a
- failure code, all cleanup must be performed as no
- PGEVT_RESULTDESTROY event will be sent for the
- destination result.
+ since PQcopyResult cannot do that. If an event
+ procedure fails (returns zero), that event procedure will be
+ ignored for the remaining lifetime of the new result; that is, it
+ will not receive PGEVT_RESULTCOPY
+ or PGEVT_RESULTDESTROY events for that result or
+ results copied from it.
mydata *res_data = dup_mydata(conn_data);
/* associate app specific data with result (copy it from conn) */
- PQsetResultInstanceData(e->result, myEventProc, res_data);
+ PQresultSetInstanceData(e->result, myEventProc, res_data);
break;
}
mydata *dest_data = dup_mydata(src_data);
/* associate app specific data with result (copy it from a result) */
- PQsetResultInstanceData(e->dest, myEventProc, dest_data);
+ PQresultSetInstanceData(e->dest, myEventProc, dest_data);
break;
}
/* Okay, trigger PGEVT_RESULTCOPY event */
for (i = 0; i < dest->nEvents; i++)
{
+ /* We don't fire events that had some previous failure */
if (src->events[i].resultInitialized)
{
PGEventResultCopy evt;
evt.src = src;
evt.dest = dest;
- if (!dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
- dest->events[i].passThrough))
- {
- PQclear(dest);
- return NULL;
- }
- dest->events[i].resultInitialized = true;
+ if (dest->events[i].proc(PGEVT_RESULTCOPY, &evt,
+ dest->events[i].passThrough))
+ dest->events[i].resultInitialized = true;
}
}
break;
}
- if (res)
- {
- int i;
-
- for (i = 0; i < res->nEvents; i++)
- {
- PGEventResultCreate evt;
-
- evt.conn = conn;
- evt.result = res;
- if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
- res->events[i].passThrough))
- {
- appendPQExpBuffer(&conn->errorMessage,
- libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
- res->events[i].name);
- pqSetResultError(res, &conn->errorMessage);
- res->resultStatus = PGRES_FATAL_ERROR;
- break;
- }
- res->events[i].resultInitialized = true;
- }
- }
+ /* Time to fire PGEVT_RESULTCREATE events, if there are any */
+ if (res && res->nEvents > 0)
+ (void) PQfireResultCreateEvents(conn, res);
return res;
}
int
PQfireResultCreateEvents(PGconn *conn, PGresult *res)
{
+ int result = true;
int i;
if (!res)
for (i = 0; i < res->nEvents; i++)
{
+ /* It's possible event was already fired, if so don't repeat it */
if (!res->events[i].resultInitialized)
{
PGEventResultCreate evt;
evt.conn = conn;
evt.result = res;
- if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
- res->events[i].passThrough))
- return false;
-
- res->events[i].resultInitialized = true;
+ if (res->events[i].proc(PGEVT_RESULTCREATE, &evt,
+ res->events[i].passThrough))
+ res->events[i].resultInitialized = true;
+ else
+ result = false;
}
}
- return true;
+ return result;
}