OSDN Git Service

Update copyright for the year 2010.
[pg-rex/syncrep.git] / src / interfaces / libpq / libpq-events.c
1 /*-------------------------------------------------------------------------
2  *
3  * libpq-events.c
4  *        functions for supporting the libpq "events" API
5  *
6  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/interfaces/libpq/libpq-events.c,v 1.6 2010/01/02 16:58:12 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres_fe.h"
16
17 #include "libpq-fe.h"
18 #include "libpq-int.h"
19
20
21 /*
22  * Registers an event proc with the given PGconn.
23  *
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().
27  *
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.
31  *
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.
35  *
36  * The function returns a non-zero if successful.  If the function fails,
37  * zero is returned.
38  */
39 int
40 PQregisterEventProc(PGconn *conn, PGEventProc proc,
41                                         const char *name, void *passThrough)
42 {
43         int                     i;
44         PGEventRegister regevt;
45
46         if (!proc || !conn || !name || !*name)
47                 return FALSE;                   /* bad arguments */
48
49         for (i = 0; i < conn->nEvents; i++)
50         {
51                 if (conn->events[i].proc == proc)
52                         return FALSE;           /* already registered */
53         }
54
55         if (conn->nEvents >= conn->eventArraySize)
56         {
57                 PGEvent    *e;
58                 int                     newSize;
59
60                 newSize = conn->eventArraySize ? conn->eventArraySize * 2 : 8;
61                 if (conn->events)
62                         e = (PGEvent *) realloc(conn->events, newSize * sizeof(PGEvent));
63                 else
64                         e = (PGEvent *) malloc(newSize * sizeof(PGEvent));
65
66                 if (!e)
67                         return FALSE;
68
69                 conn->eventArraySize = newSize;
70                 conn->events = e;
71         }
72
73         conn->events[conn->nEvents].proc = proc;
74         conn->events[conn->nEvents].name = strdup(name);
75         if (!conn->events[conn->nEvents].name)
76                 return FALSE;
77         conn->events[conn->nEvents].passThrough = passThrough;
78         conn->events[conn->nEvents].data = NULL;
79         conn->events[conn->nEvents].resultInitialized = FALSE;
80         conn->nEvents++;
81
82         regevt.conn = conn;
83         if (!proc(PGEVT_REGISTER, &regevt, passThrough))
84         {
85                 conn->nEvents--;
86                 free(conn->events[conn->nEvents].name);
87                 return FALSE;
88         }
89
90         return TRUE;
91 }
92
93 /*
94  * Set some "instance data" for an event within a PGconn.
95  * Returns nonzero on success, zero on failure.
96  */
97 int
98 PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
99 {
100         int                     i;
101
102         if (!conn || !proc)
103                 return FALSE;
104
105         for (i = 0; i < conn->nEvents; i++)
106         {
107                 if (conn->events[i].proc == proc)
108                 {
109                         conn->events[i].data = data;
110                         return TRUE;
111                 }
112         }
113
114         return FALSE;
115 }
116
117 /*
118  * Obtain the "instance data", if any, for the event.
119  */
120 void *
121 PQinstanceData(const PGconn *conn, PGEventProc proc)
122 {
123         int                     i;
124
125         if (!conn || !proc)
126                 return NULL;
127
128         for (i = 0; i < conn->nEvents; i++)
129         {
130                 if (conn->events[i].proc == proc)
131                         return conn->events[i].data;
132         }
133
134         return NULL;
135 }
136
137 /*
138  * Set some "instance data" for an event within a PGresult.
139  * Returns nonzero on success, zero on failure.
140  */
141 int
142 PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
143 {
144         int                     i;
145
146         if (!result || !proc)
147                 return FALSE;
148
149         for (i = 0; i < result->nEvents; i++)
150         {
151                 if (result->events[i].proc == proc)
152                 {
153                         result->events[i].data = data;
154                         return TRUE;
155                 }
156         }
157
158         return FALSE;
159 }
160
161 /*
162  * Obtain the "instance data", if any, for the event.
163  */
164 void *
165 PQresultInstanceData(const PGresult *result, PGEventProc proc)
166 {
167         int                     i;
168
169         if (!result || !proc)
170                 return NULL;
171
172         for (i = 0; i < result->nEvents; i++)
173                 if (result->events[i].proc == proc)
174                         return result->events[i].data;
175
176         return NULL;
177 }
178
179 /*
180  * Fire RESULTCREATE events for an application-created PGresult.
181  *
182  * The conn argument can be NULL if event procedures won't use it.
183  */
184 int
185 PQfireResultCreateEvents(PGconn *conn, PGresult *res)
186 {
187         int                     i;
188
189         if (!res)
190                 return FALSE;
191
192         for (i = 0; i < res->nEvents; i++)
193         {
194                 if (!res->events[i].resultInitialized)
195                 {
196                         PGEventResultCreate evt;
197
198                         evt.conn = conn;
199                         evt.result = res;
200                         if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
201                                                                          res->events[i].passThrough))
202                                 return FALSE;
203
204                         res->events[i].resultInitialized = TRUE;
205                 }
206         }
207
208         return TRUE;
209 }