]> begriffs open source - ai-pg/blob - full-docs/src/sgml/html/libpq-events.html
WIP: toc builder
[ai-pg] / full-docs / src / sgml / html / libpq-events.html
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>32.14. Event System</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="libpq-notice-processing.html" title="32.13. Notice Processing" /><link rel="next" href="libpq-envars.html" title="32.15. Environment Variables" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">32.14. Event System</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="libpq-notice-processing.html" title="32.13. Notice Processing">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="libpq.html" title="Chapter 32. libpq — C Library">Up</a></td><th width="60%" align="center">Chapter 32. <span class="application">libpq</span> — C Library</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="libpq-envars.html" title="32.15. Environment Variables">Next</a></td></tr></table><hr /></div><div class="sect1" id="LIBPQ-EVENTS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">32.14. Event System <a href="#LIBPQ-EVENTS" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="libpq-events.html#LIBPQ-EVENTS-TYPES">32.14.1. Event Types</a></span></dt><dt><span class="sect2"><a href="libpq-events.html#LIBPQ-EVENTS-PROC">32.14.2. Event Callback Procedure</a></span></dt><dt><span class="sect2"><a href="libpq-events.html#LIBPQ-EVENTS-FUNCS">32.14.3. Event Support Functions</a></span></dt><dt><span class="sect2"><a href="libpq-events.html#LIBPQ-EVENTS-EXAMPLE">32.14.4. Event Example</a></span></dt></dl></div><p>
3    <span class="application">libpq</span>'s event system is designed to notify
4    registered event handlers about interesting
5    <span class="application">libpq</span> events, such as the creation or
6    destruction of <code class="structname">PGconn</code> and
7    <code class="structname">PGresult</code> objects.  A principal use case is that
8    this allows applications to associate their own data with a
9    <code class="structname">PGconn</code> or <code class="structname">PGresult</code>
10    and ensure that that data is freed at an appropriate time.
11   </p><p>
12    Each registered event handler is associated with two pieces of data,
13    known to <span class="application">libpq</span> only as opaque <code class="literal">void *</code>
14    pointers.  There is a <em class="firstterm">pass-through</em> pointer that is provided
15    by the application when the event handler is registered with a
16    <code class="structname">PGconn</code>.  The pass-through pointer never changes for the
17    life of the <code class="structname">PGconn</code> and all <code class="structname">PGresult</code>s
18    generated from it; so if used, it must point to long-lived data.
19    In addition there is an <em class="firstterm">instance data</em> pointer, which starts
20    out <code class="symbol">NULL</code> in every <code class="structname">PGconn</code> and <code class="structname">PGresult</code>.
21    This pointer can be manipulated using the
22    <a class="xref" href="libpq-events.html#LIBPQ-PQINSTANCEDATA"><code class="function">PQinstanceData</code></a>,
23    <a class="xref" href="libpq-events.html#LIBPQ-PQSETINSTANCEDATA"><code class="function">PQsetInstanceData</code></a>,
24    <a class="xref" href="libpq-events.html#LIBPQ-PQRESULTINSTANCEDATA"><code class="function">PQresultInstanceData</code></a> and
25    <a class="xref" href="libpq-events.html#LIBPQ-PQRESULTSETINSTANCEDATA"><code class="function">PQresultSetInstanceData</code></a> functions.  Note that
26    unlike the pass-through pointer, instance data of a <code class="structname">PGconn</code>
27    is not automatically inherited by <code class="structname">PGresult</code>s created from
28    it.  <span class="application">libpq</span> does not know what pass-through
29    and instance data pointers point to (if anything) and will never attempt
30    to free them — that is the responsibility of the event handler.
31   </p><div class="sect2" id="LIBPQ-EVENTS-TYPES"><div class="titlepage"><div><div><h3 class="title">32.14.1. Event Types <a href="#LIBPQ-EVENTS-TYPES" class="id_link">#</a></h3></div></div></div><p>
32     The enum <code class="literal">PGEventId</code> names the types of events handled by
33     the event system.  All its values have names beginning with
34     <code class="literal">PGEVT</code>.  For each event type, there is a corresponding
35     event info structure that carries the parameters passed to the event
36     handlers.  The event types are:
37    </p><div class="variablelist"><dl class="variablelist"><dt id="LIBPQ-PGEVT-REGISTER"><span class="term"><code class="literal">PGEVT_REGISTER</code></span> <a href="#LIBPQ-PGEVT-REGISTER" class="id_link">#</a></dt><dd><p>
38        The register event occurs when <a class="xref" href="libpq-events.html#LIBPQ-PQREGISTEREVENTPROC"><code class="function">PQregisterEventProc</code></a>
39        is called.  It is the ideal time to initialize any
40        <code class="literal">instanceData</code> an event procedure may need.  Only one
41        register event will be fired per event handler per connection.  If the
42        event procedure fails (returns zero), the registration is canceled.
43
44 </p><pre class="synopsis">
45 typedef struct
46 {
47     PGconn *conn;
48 } PGEventRegister;
49 </pre><p>
50
51        When a <code class="literal">PGEVT_REGISTER</code> event is received, the
52        <em class="parameter"><code>evtInfo</code></em> pointer should be cast to a
53        <code class="structname">PGEventRegister *</code>.  This structure contains a
54        <code class="structname">PGconn</code> that should be in the
55        <code class="symbol">CONNECTION_OK</code> status; guaranteed if one calls
56        <a class="xref" href="libpq-events.html#LIBPQ-PQREGISTEREVENTPROC"><code class="function">PQregisterEventProc</code></a> right after obtaining a good
57        <code class="structname">PGconn</code>.  When returning a failure code, all
58        cleanup must be performed as no <code class="literal">PGEVT_CONNDESTROY</code>
59        event will be sent.
60       </p></dd><dt id="LIBPQ-PGEVT-CONNRESET"><span class="term"><code class="literal">PGEVT_CONNRESET</code></span> <a href="#LIBPQ-PGEVT-CONNRESET" class="id_link">#</a></dt><dd><p>
61        The connection reset event is fired on completion of
62        <a class="xref" href="libpq-connect.html#LIBPQ-PQRESET"><code class="function">PQreset</code></a> or <code class="function">PQresetPoll</code>.  In
63        both cases, the event is only fired if the reset was successful.
64        The return value of the event procedure is ignored
65        in <span class="productname">PostgreSQL</span> v15 and later.
66        With earlier versions, however, it's important to return success
67        (nonzero) or the connection will be aborted.
68
69 </p><pre class="synopsis">
70 typedef struct
71 {
72     PGconn *conn;
73 } PGEventConnReset;
74 </pre><p>
75
76        When a <code class="literal">PGEVT_CONNRESET</code> event is received, the
77        <em class="parameter"><code>evtInfo</code></em> pointer should be cast to a
78        <code class="structname">PGEventConnReset *</code>.  Although the contained
79        <code class="structname">PGconn</code> was just reset, all event data remains
80        unchanged.  This event should be used to reset/reload/requery any
81        associated <code class="literal">instanceData</code>.  Note that even if the
82        event procedure fails to process <code class="literal">PGEVT_CONNRESET</code>, it will
83        still receive a <code class="literal">PGEVT_CONNDESTROY</code> event when the connection
84        is closed.
85       </p></dd><dt id="LIBPQ-PGEVT-CONNDESTROY"><span class="term"><code class="literal">PGEVT_CONNDESTROY</code></span> <a href="#LIBPQ-PGEVT-CONNDESTROY" class="id_link">#</a></dt><dd><p>
86        The connection destroy event is fired in response to
87        <a class="xref" href="libpq-connect.html#LIBPQ-PQFINISH"><code class="function">PQfinish</code></a>.  It is the event procedure's
88        responsibility to properly clean up its event data as libpq has no
89        ability to manage this memory.  Failure to clean up will lead
90        to memory leaks.
91
92 </p><pre class="synopsis">
93 typedef struct
94 {
95     PGconn *conn;
96 } PGEventConnDestroy;
97 </pre><p>
98
99        When a <code class="literal">PGEVT_CONNDESTROY</code> event is received, the
100        <em class="parameter"><code>evtInfo</code></em> pointer should be cast to a
101        <code class="structname">PGEventConnDestroy *</code>.  This event is fired
102        prior to <a class="xref" href="libpq-connect.html#LIBPQ-PQFINISH"><code class="function">PQfinish</code></a> performing any other cleanup.
103        The return value of the event procedure is ignored since there is no
104        way of indicating a failure from <a class="xref" href="libpq-connect.html#LIBPQ-PQFINISH"><code class="function">PQfinish</code></a>.  Also,
105        an event procedure failure should not abort the process of cleaning up
106        unwanted memory.
107       </p></dd><dt id="LIBPQ-PGEVT-RESULTCREATE"><span class="term"><code class="literal">PGEVT_RESULTCREATE</code></span> <a href="#LIBPQ-PGEVT-RESULTCREATE" class="id_link">#</a></dt><dd><p>
108        The result creation event is fired in response to any query execution
109        function that generates a result, including
110        <a class="xref" href="libpq-async.html#LIBPQ-PQGETRESULT"><code class="function">PQgetResult</code></a>.  This event will only be fired after
111        the result has been created successfully.
112
113 </p><pre class="synopsis">
114 typedef struct
115 {
116     PGconn *conn;
117     PGresult *result;
118 } PGEventResultCreate;
119 </pre><p>
120
121        When a <code class="literal">PGEVT_RESULTCREATE</code> event is received, the
122        <em class="parameter"><code>evtInfo</code></em> pointer should be cast to a
123        <code class="structname">PGEventResultCreate *</code>.  The
124        <em class="parameter"><code>conn</code></em> is the connection used to generate the
125        result.  This is the ideal place to initialize any
126        <code class="literal">instanceData</code> that needs to be associated with the
127        result.  If an event procedure fails (returns zero), that event
128        procedure will be ignored for the remaining lifetime of the result;
129        that is, it will not receive <code class="literal">PGEVT_RESULTCOPY</code>
130        or <code class="literal">PGEVT_RESULTDESTROY</code> events for this result or
131        results copied from it.
132       </p></dd><dt id="LIBPQ-PGEVT-RESULTCOPY"><span class="term"><code class="literal">PGEVT_RESULTCOPY</code></span> <a href="#LIBPQ-PGEVT-RESULTCOPY" class="id_link">#</a></dt><dd><p>
133        The result copy event is fired in response to
134        <a class="xref" href="libpq-misc.html#LIBPQ-PQCOPYRESULT"><code class="function">PQcopyResult</code></a>.  This event will only be fired after
135        the copy is complete.  Only event procedures that have
136        successfully handled the <code class="literal">PGEVT_RESULTCREATE</code>
137        or <code class="literal">PGEVT_RESULTCOPY</code> event for the source result
138        will receive <code class="literal">PGEVT_RESULTCOPY</code> events.
139
140 </p><pre class="synopsis">
141 typedef struct
142 {
143     const PGresult *src;
144     PGresult *dest;
145 } PGEventResultCopy;
146 </pre><p>
147
148        When a <code class="literal">PGEVT_RESULTCOPY</code> event is received, the
149        <em class="parameter"><code>evtInfo</code></em> pointer should be cast to a
150        <code class="structname">PGEventResultCopy *</code>.  The
151        <em class="parameter"><code>src</code></em> result is what was copied while the
152        <em class="parameter"><code>dest</code></em> result is the copy destination.  This event
153        can be used to provide a deep copy of <code class="literal">instanceData</code>,
154        since <code class="literal">PQcopyResult</code> cannot do that.  If an event
155        procedure fails (returns zero), that event procedure will be
156        ignored for the remaining lifetime of the new result; that is, it
157        will not receive <code class="literal">PGEVT_RESULTCOPY</code>
158        or <code class="literal">PGEVT_RESULTDESTROY</code> events for that result or
159        results copied from it.
160       </p></dd><dt id="LIBPQ-PGEVT-RESULTDESTROY"><span class="term"><code class="literal">PGEVT_RESULTDESTROY</code></span> <a href="#LIBPQ-PGEVT-RESULTDESTROY" class="id_link">#</a></dt><dd><p>
161        The result destroy event is fired in response to a
162        <a class="xref" href="libpq-exec.html#LIBPQ-PQCLEAR"><code class="function">PQclear</code></a>.  It is the event procedure's
163        responsibility to properly clean up its event data as libpq has no
164        ability to manage this memory.  Failure to clean up will lead
165        to memory leaks.
166
167 </p><pre class="synopsis">
168 typedef struct
169 {
170     PGresult *result;
171 } PGEventResultDestroy;
172 </pre><p>
173
174        When a <code class="literal">PGEVT_RESULTDESTROY</code> event is received, the
175        <em class="parameter"><code>evtInfo</code></em> pointer should be cast to a
176        <code class="structname">PGEventResultDestroy *</code>.  This event is fired
177        prior to <a class="xref" href="libpq-exec.html#LIBPQ-PQCLEAR"><code class="function">PQclear</code></a> performing any other cleanup.
178        The return value of the event procedure is ignored since there is no
179        way of indicating a failure from <a class="xref" href="libpq-exec.html#LIBPQ-PQCLEAR"><code class="function">PQclear</code></a>.  Also,
180        an event procedure failure should not abort the process of cleaning up
181        unwanted memory.
182       </p></dd></dl></div></div><div class="sect2" id="LIBPQ-EVENTS-PROC"><div class="titlepage"><div><div><h3 class="title">32.14.2. Event Callback Procedure <a href="#LIBPQ-EVENTS-PROC" class="id_link">#</a></h3></div></div></div><div class="variablelist"><dl class="variablelist"><dt id="LIBPQ-PGEVENTPROC"><span class="term"><code class="literal">PGEventProc</code><a id="id-1.7.3.21.5.2.1.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PGEVENTPROC" class="id_link">#</a></dt><dd><p>
183        <code class="literal">PGEventProc</code> is a typedef for a pointer to an
184        event procedure, that is, the user callback function that receives
185        events from libpq.  The signature of an event procedure must be
186
187 </p><pre class="synopsis">
188 int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)
189 </pre><p>
190
191        The <em class="parameter"><code>evtId</code></em> parameter indicates which
192        <code class="literal">PGEVT</code> event occurred.  The
193        <em class="parameter"><code>evtInfo</code></em> pointer must be cast to the appropriate
194        structure type to obtain further information about the event.
195        The <em class="parameter"><code>passThrough</code></em> parameter is the pointer
196        provided to <a class="xref" href="libpq-events.html#LIBPQ-PQREGISTEREVENTPROC"><code class="function">PQregisterEventProc</code></a> when the event
197        procedure was registered.  The function should return a non-zero value
198        if it succeeds and zero if it fails.
199       </p><p>
200        A particular event procedure can be registered only once in any
201        <code class="structname">PGconn</code>.  This is because the address of the procedure
202        is used as a lookup key to identify the associated instance data.
203       </p><div class="caution"><h3 class="title">Caution</h3><p>
204         On Windows, functions can have two different addresses: one visible
205         from outside a DLL and another visible from inside the DLL.  One
206         should be careful that only one of these addresses is used with
207         <span class="application">libpq</span>'s event-procedure functions, else confusion will
208         result.  The simplest rule for writing code that will work is to
209         ensure that event procedures are declared <code class="literal">static</code>.  If the
210         procedure's address must be available outside its own source file,
211         expose a separate function to return the address.
212        </p></div></dd></dl></div></div><div class="sect2" id="LIBPQ-EVENTS-FUNCS"><div class="titlepage"><div><div><h3 class="title">32.14.3. Event Support Functions <a href="#LIBPQ-EVENTS-FUNCS" class="id_link">#</a></h3></div></div></div><div class="variablelist"><dl class="variablelist"><dt id="LIBPQ-PQREGISTEREVENTPROC"><span class="term"><code class="function">PQregisterEventProc</code><a id="id-1.7.3.21.6.2.1.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQREGISTEREVENTPROC" class="id_link">#</a></dt><dd><p>
213        Registers an event callback procedure with libpq.
214
215 </p><pre class="synopsis">
216 int PQregisterEventProc(PGconn *conn, PGEventProc proc,
217                         const char *name, void *passThrough);
218 </pre><p>
219       </p><p>
220        An event procedure must be registered once on each
221        <code class="structname">PGconn</code> you want to receive events about.  There is no
222        limit, other than memory, on the number of event procedures that
223        can be registered with a connection.  The function returns a non-zero
224        value if it succeeds and zero if it fails.
225       </p><p>
226        The <em class="parameter"><code>proc</code></em> argument will be called when a libpq
227        event is fired.  Its memory address is also used to lookup
228        <code class="literal">instanceData</code>.  The <em class="parameter"><code>name</code></em>
229        argument is used to refer to the event procedure in error messages.
230        This value cannot be <code class="symbol">NULL</code> or a zero-length string.  The name string is
231        copied into the <code class="structname">PGconn</code>, so what is passed need not be
232        long-lived.  The <em class="parameter"><code>passThrough</code></em> pointer is passed
233        to the <em class="parameter"><code>proc</code></em> whenever an event occurs. This
234        argument can be <code class="symbol">NULL</code>.
235       </p></dd><dt id="LIBPQ-PQSETINSTANCEDATA"><span class="term"><code class="function">PQsetInstanceData</code><a id="id-1.7.3.21.6.2.2.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQSETINSTANCEDATA" class="id_link">#</a></dt><dd><p>
236        Sets the connection <em class="parameter"><code>conn</code></em>'s <code class="literal">instanceData</code>
237        for procedure <em class="parameter"><code>proc</code></em> to <em class="parameter"><code>data</code></em>.  This
238        returns non-zero for success and zero for failure.  (Failure is
239        only possible if <em class="parameter"><code>proc</code></em> has not been properly
240        registered in <em class="parameter"><code>conn</code></em>.)
241
242 </p><pre class="synopsis">
243 int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);
244 </pre><p>
245       </p></dd><dt id="LIBPQ-PQINSTANCEDATA"><span class="term"><code class="function">PQinstanceData</code><a id="id-1.7.3.21.6.2.3.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQINSTANCEDATA" class="id_link">#</a></dt><dd><p>
246        Returns the
247        connection <em class="parameter"><code>conn</code></em>'s <code class="literal">instanceData</code>
248        associated with procedure <em class="parameter"><code>proc</code></em>,
249        or <code class="symbol">NULL</code> if there is none.
250
251 </p><pre class="synopsis">
252 void *PQinstanceData(const PGconn *conn, PGEventProc proc);
253 </pre><p>
254       </p></dd><dt id="LIBPQ-PQRESULTSETINSTANCEDATA"><span class="term"><code class="function">PQresultSetInstanceData</code><a id="id-1.7.3.21.6.2.4.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQRESULTSETINSTANCEDATA" class="id_link">#</a></dt><dd><p>
255        Sets the result's <code class="literal">instanceData</code>
256        for <em class="parameter"><code>proc</code></em> to <em class="parameter"><code>data</code></em>.  This returns
257        non-zero for success and zero for failure.  (Failure is only
258        possible if <em class="parameter"><code>proc</code></em> has not been properly registered
259        in the result.)
260
261 </p><pre class="synopsis">
262 int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data);
263 </pre><p>
264       </p><p>
265        Beware that any storage represented by <em class="parameter"><code>data</code></em>
266        will not be accounted for by <a class="xref" href="libpq-misc.html#LIBPQ-PQRESULTMEMORYSIZE"><code class="function">PQresultMemorySize</code></a>,
267        unless it is allocated using <a class="xref" href="libpq-misc.html#LIBPQ-PQRESULTALLOC"><code class="function">PQresultAlloc</code></a>.
268        (Doing so is recommendable because it eliminates the need to free
269        such storage explicitly when the result is destroyed.)
270       </p></dd><dt id="LIBPQ-PQRESULTINSTANCEDATA"><span class="term"><code class="function">PQresultInstanceData</code><a id="id-1.7.3.21.6.2.5.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQRESULTINSTANCEDATA" class="id_link">#</a></dt><dd><p>
271        Returns the result's <code class="literal">instanceData</code> associated with <em class="parameter"><code>proc</code></em>, or <code class="symbol">NULL</code>
272        if there is none.
273
274 </p><pre class="synopsis">
275 void *PQresultInstanceData(const PGresult *res, PGEventProc proc);
276 </pre><p>
277       </p></dd></dl></div></div><div class="sect2" id="LIBPQ-EVENTS-EXAMPLE"><div class="titlepage"><div><div><h3 class="title">32.14.4. Event Example <a href="#LIBPQ-EVENTS-EXAMPLE" class="id_link">#</a></h3></div></div></div><p>
278     Here is a skeleton example of managing private data associated with
279     libpq connections and results.
280    </p><pre class="programlisting">
281
282 /* required header for libpq events (note: includes libpq-fe.h) */
283 #include &lt;libpq-events.h&gt;
284
285 /* The instanceData */
286 typedef struct
287 {
288     int n;
289     char *str;
290 } mydata;
291
292 /* PGEventProc */
293 static int myEventProc(PGEventId evtId, void *evtInfo, void *passThrough);
294
295 int
296 main(void)
297 {
298     mydata *data;
299     PGresult *res;
300     PGconn *conn =
301         PQconnectdb("dbname=postgres options=-csearch_path=");
302
303     if (PQstatus(conn) != CONNECTION_OK)
304     {
305         /* PQerrorMessage's result includes a trailing newline */
306         fprintf(stderr, "%s", PQerrorMessage(conn));
307         PQfinish(conn);
308         return 1;
309     }
310
311     /* called once on any connection that should receive events.
312      * Sends a PGEVT_REGISTER to myEventProc.
313      */
314     if (!PQregisterEventProc(conn, myEventProc, "mydata_proc", NULL))
315     {
316         fprintf(stderr, "Cannot register PGEventProc\n");
317         PQfinish(conn);
318         return 1;
319     }
320
321     /* conn instanceData is available */
322     data = PQinstanceData(conn, myEventProc);
323
324     /* Sends a PGEVT_RESULTCREATE to myEventProc */
325     res = PQexec(conn, "SELECT 1 + 1");
326
327     /* result instanceData is available */
328     data = PQresultInstanceData(res, myEventProc);
329
330     /* If PG_COPYRES_EVENTS is used, sends a PGEVT_RESULTCOPY to myEventProc */
331     res_copy = PQcopyResult(res, PG_COPYRES_TUPLES | PG_COPYRES_EVENTS);
332
333     /* result instanceData is available if PG_COPYRES_EVENTS was
334      * used during the PQcopyResult call.
335      */
336     data = PQresultInstanceData(res_copy, myEventProc);
337
338     /* Both clears send a PGEVT_RESULTDESTROY to myEventProc */
339     PQclear(res);
340     PQclear(res_copy);
341
342     /* Sends a PGEVT_CONNDESTROY to myEventProc */
343     PQfinish(conn);
344
345     return 0;
346 }
347
348 static int
349 myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
350 {
351     switch (evtId)
352     {
353         case PGEVT_REGISTER:
354         {
355             PGEventRegister *e = (PGEventRegister *)evtInfo;
356             mydata *data = get_mydata(e-&gt;conn);
357
358             /* associate app specific data with connection */
359             PQsetInstanceData(e-&gt;conn, myEventProc, data);
360             break;
361         }
362
363         case PGEVT_CONNRESET:
364         {
365             PGEventConnReset *e = (PGEventConnReset *)evtInfo;
366             mydata *data = PQinstanceData(e-&gt;conn, myEventProc);
367
368             if (data)
369               memset(data, 0, sizeof(mydata));
370             break;
371         }
372
373         case PGEVT_CONNDESTROY:
374         {
375             PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo;
376             mydata *data = PQinstanceData(e-&gt;conn, myEventProc);
377
378             /* free instance data because the conn is being destroyed */
379             if (data)
380               free_mydata(data);
381             break;
382         }
383
384         case PGEVT_RESULTCREATE:
385         {
386             PGEventResultCreate *e = (PGEventResultCreate *)evtInfo;
387             mydata *conn_data = PQinstanceData(e-&gt;conn, myEventProc);
388             mydata *res_data = dup_mydata(conn_data);
389
390             /* associate app specific data with result (copy it from conn) */
391             PQresultSetInstanceData(e-&gt;result, myEventProc, res_data);
392             break;
393         }
394
395         case PGEVT_RESULTCOPY:
396         {
397             PGEventResultCopy *e = (PGEventResultCopy *)evtInfo;
398             mydata *src_data = PQresultInstanceData(e-&gt;src, myEventProc);
399             mydata *dest_data = dup_mydata(src_data);
400
401             /* associate app specific data with result (copy it from a result) */
402             PQresultSetInstanceData(e-&gt;dest, myEventProc, dest_data);
403             break;
404         }
405
406         case PGEVT_RESULTDESTROY:
407         {
408             PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo;
409             mydata *data = PQresultInstanceData(e-&gt;result, myEventProc);
410
411             /* free instance data because the result is being destroyed */
412             if (data)
413               free_mydata(data);
414             break;
415         }
416
417         /* unknown event ID, just return true. */
418         default:
419             break;
420     }
421
422     return true; /* event processing succeeded */
423 }
424
425 </pre></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="libpq-notice-processing.html" title="32.13. Notice Processing">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="libpq.html" title="Chapter 32. libpq — C Library">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="libpq-envars.html" title="32.15. Environment Variables">Next</a></td></tr><tr><td width="40%" align="left" valign="top">32.13. Notice Processing </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 32.15. Environment Variables</td></tr></table></div></body></html>