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.
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.
44 </p><pre class="synopsis">
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>
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.
69 </p><pre class="synopsis">
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
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
92 </p><pre class="synopsis">
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
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.
113 </p><pre class="synopsis">
118 } PGEventResultCreate;
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.
140 </p><pre class="synopsis">
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
167 </p><pre class="synopsis">
171 } PGEventResultDestroy;
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
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
187 </p><pre class="synopsis">
188 int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)
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.
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.
215 </p><pre class="synopsis">
216 int PQregisterEventProc(PGconn *conn, PGEventProc proc,
217 const char *name, void *passThrough);
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.
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>.)
242 </p><pre class="synopsis">
243 int PQsetInstanceData(PGconn *conn, PGEventProc proc, void *data);
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>
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.
251 </p><pre class="synopsis">
252 void *PQinstanceData(const PGconn *conn, PGEventProc proc);
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
261 </p><pre class="synopsis">
262 int PQresultSetInstanceData(PGresult *res, PGEventProc proc, void *data);
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>
274 </p><pre class="synopsis">
275 void *PQresultInstanceData(const PGresult *res, PGEventProc proc);
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">
282 /* required header for libpq events (note: includes libpq-fe.h) */
283 #include <libpq-events.h>
285 /* The instanceData */
293 static int myEventProc(PGEventId evtId, void *evtInfo, void *passThrough);
301 PQconnectdb("dbname=postgres options=-csearch_path=");
303 if (PQstatus(conn) != CONNECTION_OK)
305 /* PQerrorMessage's result includes a trailing newline */
306 fprintf(stderr, "%s", PQerrorMessage(conn));
311 /* called once on any connection that should receive events.
312 * Sends a PGEVT_REGISTER to myEventProc.
314 if (!PQregisterEventProc(conn, myEventProc, "mydata_proc", NULL))
316 fprintf(stderr, "Cannot register PGEventProc\n");
321 /* conn instanceData is available */
322 data = PQinstanceData(conn, myEventProc);
324 /* Sends a PGEVT_RESULTCREATE to myEventProc */
325 res = PQexec(conn, "SELECT 1 + 1");
327 /* result instanceData is available */
328 data = PQresultInstanceData(res, myEventProc);
330 /* If PG_COPYRES_EVENTS is used, sends a PGEVT_RESULTCOPY to myEventProc */
331 res_copy = PQcopyResult(res, PG_COPYRES_TUPLES | PG_COPYRES_EVENTS);
333 /* result instanceData is available if PG_COPYRES_EVENTS was
334 * used during the PQcopyResult call.
336 data = PQresultInstanceData(res_copy, myEventProc);
338 /* Both clears send a PGEVT_RESULTDESTROY to myEventProc */
342 /* Sends a PGEVT_CONNDESTROY to myEventProc */
349 myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
355 PGEventRegister *e = (PGEventRegister *)evtInfo;
356 mydata *data = get_mydata(e->conn);
358 /* associate app specific data with connection */
359 PQsetInstanceData(e->conn, myEventProc, data);
363 case PGEVT_CONNRESET:
365 PGEventConnReset *e = (PGEventConnReset *)evtInfo;
366 mydata *data = PQinstanceData(e->conn, myEventProc);
369 memset(data, 0, sizeof(mydata));
373 case PGEVT_CONNDESTROY:
375 PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo;
376 mydata *data = PQinstanceData(e->conn, myEventProc);
378 /* free instance data because the conn is being destroyed */
384 case PGEVT_RESULTCREATE:
386 PGEventResultCreate *e = (PGEventResultCreate *)evtInfo;
387 mydata *conn_data = PQinstanceData(e->conn, myEventProc);
388 mydata *res_data = dup_mydata(conn_data);
390 /* associate app specific data with result (copy it from conn) */
391 PQresultSetInstanceData(e->result, myEventProc, res_data);
395 case PGEVT_RESULTCOPY:
397 PGEventResultCopy *e = (PGEventResultCopy *)evtInfo;
398 mydata *src_data = PQresultInstanceData(e->src, myEventProc);
399 mydata *dest_data = dup_mydata(src_data);
401 /* associate app specific data with result (copy it from a result) */
402 PQresultSetInstanceData(e->dest, myEventProc, dest_data);
406 case PGEVT_RESULTDESTROY:
408 PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo;
409 mydata *data = PQresultInstanceData(e->result, myEventProc);
411 /* free instance data because the result is being destroyed */
417 /* unknown event ID, just return true. */
422 return true; /* event processing succeeded */
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>