~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/interfaces/libpq/libpq-events.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * libpq-events.c
 
4
 *        functions for supporting the libpq "events" API
 
5
 *
 
6
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL$
 
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
}