libpq's event system is
designed to notify registered event handlers about interesting
libpq events, such as the
creation or destruction of PGconn and
PGresult objects. A principal use
case is that this allows applications to associate their own data
with a PGconn or PGresult and ensure that that data is freed at
an appropriate time.

Each registered event handler is associated with two pieces of
data, known to libpq only as
opaque void * pointers. There is a
passthrough pointer that is provided by
the application when the event handler is registered with a
PGconn. The passthrough pointer never
changes for the life of the PGconn
and all PGresults generated from it;
so if used, it must point to long-lived data. In addition there
is an instance data pointer, which
starts out NULL in every PGconn and PGresult. This pointer can be manipulated using
the PQinstanceData, PQsetInstanceData, PQresultInstanceData and PQsetResultInstanceData functions. Note that
unlike the passthrough pointer, instance data of a PGconn is not automatically inherited by
PGresults created from it.
libpq does not know what
passthrough and instance data pointers point to (if anything) and
will never attempt to free them — that is the responsibility of
the event handler.

The enum PGEventId names the types
of events handled by the event system. All its values have
names beginning with PGEVT. For each
event type, there is a corresponding event info structure that
carries the parameters passed to the event handlers. The event
types are:

PGEVT_REGISTER

The register event occurs when PQregisterEventProc 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.

typedef struct
{
PGconn *conn;
} PGEventRegister;

When a PGEVT_REGISTER event
is received, the evtInfo
pointer should be cast to a PGEventRegister *. This structure
contains a PGconn that should
be in the CONNECTION_OK status;
guaranteed if one calls PQregisterEventProc right after
obtaining a good PGconn. When
returning a failure code, all cleanup must be performed
as no PGEVT_CONNDESTROY event
will be sent.

PGEVT_CONNRESET

The connection reset event is fired on completion of
PQreset or PQresetPoll. In both cases, the event
is only fired if the reset was successful. If the event
procedure fails, the entire connection reset will fail;
the PGconn is put into
CONNECTION_BAD status and
PQresetPoll will return
PGRES_POLLING_FAILED.

typedef struct
{
PGconn *conn;
} PGEventConnReset;

When a PGEVT_CONNRESET event
is received, the evtInfo
pointer should be cast to a PGEventConnReset *. Although the
contained PGconn was just
reset, all event data remains unchanged. This event
should be used to reset/reload/requery any associated
instanceData. Note that even if
the event procedure fails to process PGEVT_CONNRESET, it will still receive a
PGEVT_CONNDESTROY event when the
connection is closed.

PGEVT_CONNDESTROY

The connection destroy event is fired in response to
PQfinish. It is the event
procedure's responsibility to properly clean up its event
data as libpq has no ability to manage this memory.
Failure to clean up will lead to memory leaks.

typedef struct
{
PGconn *conn;
} PGEventConnDestroy;

When a PGEVT_CONNDESTROY
event is received, the evtInfo
pointer should be cast to a PGEventConnDestroy *. This event is
fired prior to PQfinish
performing any other cleanup. The return value of the
event procedure is ignored since there is no way of
indicating a failure from PQfinish. Also, an event procedure
failure should not abort the process of cleaning up
unwanted memory.

PGEVT_RESULTCREATE

The result creation event is fired in response to any
query execution function that generates a result,
including PQgetResult. This
event will only be fired after the result has been
created successfully.

When a PGEVT_RESULTCREATE
event is received, the evtInfo
pointer should be cast to a PGEventResultCreate *. The 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
PQclear the result object
for itself. When returning a failure code, all cleanup
must be performed as no PGEVT_RESULTDESTROY event will be
sent.

PGEVT_RESULTCOPY

The result copy event is fired in response to
PQcopyResult. This event
will only be fired after the copy is complete. Only event
procedures that have successfully handled the PGEVT_RESULTCREATE or PGEVT_RESULTCOPY event for the source
result will receive PGEVT_RESULTCOPY events.

When a PGEVT_RESULTCOPY event
is received, the evtInfo
pointer should be cast to a PGEventResultCopy *. The 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.

PGEVT_RESULTDESTROY

The result destroy event is fired in response to a
PQclear. It is the event
procedure's responsibility to properly clean up its event
data as libpq has no ability to manage this memory.
Failure to clean up will lead to memory leaks.

typedef struct
{
PGresult *result;
} PGEventResultDestroy;

When a PGEVT_RESULTDESTROY
event is received, the evtInfo
pointer should be cast to a PGEventResultDestroy *. This event is
fired prior to PQclear
performing any other cleanup. The return value of the
event procedure is ignored since there is no way of
indicating a failure from PQclear. Also, an event procedure
failure should not abort the process of cleaning up
unwanted memory.

PGEventProc is a typedef for
a pointer to an event procedure, that is, the user
callback function that receives events from libpq. The
signature of an event procedure must be

int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)

The evtId parameter
indicates which PGEVT event
occurred. The evtInfo pointer
must be cast to the appropriate structure type to obtain
further information about the event. The passThrough parameter is the pointer
provided to PQregisterEventProc when the event
procedure was registered. The function should return a
non-zero value if it succeeds and zero if it fails.

A particular event procedure can be registered only
once in any PGconn. This is
because the address of the procedure is used as a lookup
key to identify the associated instance data.

Caution

On Windows, functions can have two different
addresses: one visible from outside a DLL and
another visible from inside the DLL. One should
be careful that only one of these addresses is
used with libpq's event-procedure
functions, else confusion will result. The
simplest rule for writing code that will work is
to ensure that event procedures are declared
static. If the
procedure's address must be available outside its
own source file, expose a separate function to
return the address.

An event procedure must be registered once on each
PGconn you want to receive
events about. There is no limit, other than memory, on
the number of event procedures that can be registered
with a connection. The function returns a non-zero value
if it succeeds and zero if it fails.

The proc argument will be
called when a libpq event is fired. Its memory address is
also used to lookup instanceData. The name argument is used to refer to the
event procedure in error messages. This value cannot be
NULL or a zero-length string. The
name string is copied into the PGconn, so what is passed need not be
long-lived. The passThrough
pointer is passed to the proc
whenever an event occurs. This argument can be NULL.

PQsetInstanceData

Sets the connection conn's
instanceData for procedure
proc to data. This returns non-zero for success
and zero for failure. (Failure is only possible if
proc has not been properly
registered in conn.)

int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);

PQinstanceData

Returns the connection conn's instanceData associated with procedure
proc, or NULL if there is none.

void *PQinstanceData(const PGconn *conn, PGEventProc proc);

PQresultSetInstanceData

Sets the result's instanceData for proc to data.
This returns non-zero for success and zero for failure.
(Failure is only possible if proc has not been properly registered in
the result.)