PostgreSQL Source Code  git master
libpq-events.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * libpq-events.c
4  * functions for supporting the libpq "events" API
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/interfaces/libpq/libpq-events.c
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
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 
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;
80  conn->nEvents++;
81 
82  regevt.conn = conn;
83  if (!proc(PGEVT_REGISTER, &regevt, passThrough))
84  {
85  conn->nEvents--;
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
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 *
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
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 *
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
186 {
187  int result = true;
188  int i;
189 
190  if (!res)
191  return false;
192 
193  for (i = 0; i < res->nEvents; i++)
194  {
195  /* It's possible event was already fired, if so don't repeat it */
196  if (!res->events[i].resultInitialized)
197  {
199 
200  evt.conn = conn;
201  evt.result = res;
202  if (res->events[i].proc(PGEVT_RESULTCREATE, &evt,
203  res->events[i].passThrough))
204  res->events[i].resultInitialized = true;
205  else
206  result = false;
207  }
208  }
209 
210  return result;
211 }
#define realloc(a, b)
Definition: header.h:60
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
int i
Definition: isn.c:73
void * PQresultInstanceData(const PGresult *result, PGEventProc proc)
Definition: libpq-events.c:165
int PQresultSetInstanceData(PGresult *result, PGEventProc proc, void *data)
Definition: libpq-events.c:142
void * PQinstanceData(const PGconn *conn, PGEventProc proc)
Definition: libpq-events.c:121
int PQfireResultCreateEvents(PGconn *conn, PGresult *res)
Definition: libpq-events.c:185
int PQregisterEventProc(PGconn *conn, PGEventProc proc, const char *name, void *passThrough)
Definition: libpq-events.c:40
int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data)
Definition: libpq-events.c:98
@ PGEVT_RESULTCREATE
Definition: libpq-events.h:32
@ PGEVT_REGISTER
Definition: libpq-events.h:29
int(* PGEventProc)(PGEventId evtId, void *evtInfo, void *passThrough)
Definition: libpq-events.h:69
const void * data
e
Definition: preproc-init.c:82
PGconn * conn
Definition: streamutil.c:55
void * passThrough
Definition: libpq-int.h:165
char * name
Definition: libpq-int.h:164
void * data
Definition: libpq-int.h:166
PGEventProc proc
Definition: libpq-int.h:163
bool resultInitialized
Definition: libpq-int.h:167
int nEvents
Definition: libpq-int.h:434
int eventArraySize
Definition: libpq-int.h:435
PGEvent * events
Definition: libpq-int.h:433
int nEvents
Definition: libpq-int.h:191
PGEvent * events
Definition: libpq-int.h:190
const char * name