1
/*-------------------------------------------------------------------------
4
* functions for supporting the libpq "events" API
6
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* src/interfaces/libpq/libpq-events.c
13
*-------------------------------------------------------------------------
15
#include "postgres_fe.h"
18
#include "libpq-int.h"
22
* Registers an event proc with the given PGconn.
24
* The same proc can't be registered more than once in a PGconn. This
25
* restriction is required because we use the proc address to identify
26
* the event for purposes such as PQinstanceData().
28
* The name argument is used within error messages to aid in debugging.
29
* A name must be supplied, but it needn't be unique. The string is
30
* copied, so the passed value needn't be long-lived.
32
* The passThrough argument is an application specific pointer and can be set
33
* to NULL if not required. It is passed through to the event proc whenever
34
* the event proc is called, and is not otherwise touched by libpq.
36
* The function returns a non-zero if successful. If the function fails,
40
PQregisterEventProc(PGconn *conn, PGEventProc proc,
41
const char *name, void *passThrough)
44
PGEventRegister regevt;
46
if (!proc || !conn || !name || !*name)
47
return FALSE; /* bad arguments */
49
for (i = 0; i < conn->nEvents; i++)
51
if (conn->events[i].proc == proc)
52
return FALSE; /* already registered */
55
if (conn->nEvents >= conn->eventArraySize)
60
newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
62
e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
64
e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
69
conn->eventArraySize = newSize;
73
conn->events[conn->nEvents].proc = proc;
74
conn->events[conn->nEvents].name = strdup(name);
75
if (!conn->events[conn->nEvents].name)
77
conn->events[conn->nEvents].passThrough = passThrough;
78
conn->events[conn->nEvents].data = NULL;
79
conn->events[conn->nEvents].resultInitialized = FALSE;
83
if (!proc(PGEVT_REGISTER, ®evt, passThrough))
86
free(conn->events[conn->nEvents].name);
94
* Set some "instance data" for an event within a PGconn.
95
* Returns nonzero on success, zero on failure.
98
PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
105
for (i = 0; i < conn->nEvents; i++)
107
if (conn->events[i].proc == proc)
109
conn->events[i].data = data;
118
* Obtain the "instance data", if any, for the event.
121
PQinstanceData(const PGconn *conn, PGEventProc proc)
128
for (i = 0; i < conn->nEvents; i++)
130
if (conn->events[i].proc == proc)
131
return conn->events[i].data;
138
* Set some "instance data" for an event within a PGresult.
139
* Returns nonzero on success, zero on failure.
142
PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
146
if (!result || !proc)
149
for (i = 0; i < result->nEvents; i++)
151
if (result->events[i].proc == proc)
153
result->events[i].data = data;
162
* Obtain the "instance data", if any, for the event.
165
PQresultInstanceData(const PGresult *result, PGEventProc proc)
169
if (!result || !proc)
172
for (i = 0; i < result->nEvents; i++)
173
if (result->events[i].proc == proc)
174
return result->events[i].data;
180
* Fire RESULTCREATE events for an application-created PGresult.
182
* The conn argument can be NULL if event procedures won't use it.
185
PQfireResultCreateEvents(PGconn *conn, PGresult *res)
192
for (i = 0; i < res->nEvents; i++)
194
if (!res->events[i].resultInitialized)
196
PGEventResultCreate evt;
200
if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
201
res->events[i].passThrough))
204
res->events[i].resultInitialized = TRUE;