1 /*-------------------------------------------------------------------------
4 * functions for supporting the libpq "events" API
6 * Portions Copyright (c) 1996-2015, 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;