1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>28.4.Asynchronous Command Processing</title>
<link rel="stylesheet" href="stylesheet.css" type="text/css">
<link rev="made" href="pgsql-docs@postgresql.org">
<meta name="generator" content="DocBook XSL Stylesheets V1.70.0">
<link rel="start" href="index.html" title="PostgreSQL 8.1.4 Documentation">
<link rel="up" href="libpq.html" title="Chapter28.libpq - C Library">
<link rel="prev" href="libpq-exec.html" title="28.3.Command Execution Functions">
<link rel="next" href="libpq-cancel.html" title="28.5.Cancelling Queries in Progress">
<link rel="copyright" href="ln-legalnotice.html" title="Legal Notice">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="sect1" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="libpq-async"></a>28.4.Asynchronous Command Processing</h2></div></div></div>
<a name="id682031"></a><p>The <code class="function">PQexec</code> function is adequate for submitting commands in
normal, synchronous
applications. It has a couple of deficiencies, however, that can be of importance to some users:
</p>
<div class="itemizedlist"><ul type="disc">
<li><p><code class="function">PQexec</code> waits for the command to be completed. The application may have other
work to do (such as maintaining a user interface), in which case it won't
want to block waiting for the response.</p></li>
<li><p>Since the execution of the client application is suspended while it
waits for the result, it is hard for the application to decide that it
would like to try to cancel the ongoing command. (It can be done from
a signal handler, but not otherwise.)</p></li>
<li><p><code class="function">PQexec</code> can return only one <code class="structname">PGresult</code> structure. If the submitted command
string contains multiple <acronym class="acronym">SQL</acronym> commands, all but the last <code class="structname">PGresult</code> are
discarded by <code class="function">PQexec</code>.</p></li>
</ul></div>
<p>Applications that do not like these limitations can instead use the
underlying functions that <code class="function">PQexec</code> is built from:
<code class="function">PQsendQuery</code> and <code class="function">PQgetResult</code>.
There are also
<code class="function">PQsendQueryParams</code>,
<code class="function">PQsendPrepare</code>, and
<code class="function">PQsendQueryPrepared</code>,
which can be used with <code class="function">PQgetResult</code> to duplicate the
functionality of
<code class="function">PQexecParams</code>,
<code class="function">PQprepare</code>, and
<code class="function">PQexecPrepared</code>
respectively.
</p>
<div class="variablelist"><dl>
<dt><span class="term"><code class="function">PQsendQuery</code><a name="id682186"></a></span></dt>
<dd>
<p> Submits a command to the server without
waiting for the result(s). 1 is returned if the command was
successfully dispatched and 0 if not (in which case, use
<code class="function">PQerrorMessage</code> to get more information about the failure).
</p>
<pre class="synopsis">int PQsendQuery(PGconn *conn, const char *command);</pre>
<p>
After successfully calling <code class="function">PQsendQuery</code>, call
<code class="function">PQgetResult</code> one or more
times to obtain the results. <code class="function">PQsendQuery</code> may not be called
again (on the same connection) until <code class="function">PQgetResult</code> has returned a null pointer,
indicating that the command is done.</p>
</dd>
<dt><span class="term"><code class="function">PQsendQueryParams</code><a name="id682252"></a></span></dt>
<dd>
<p> Submits a command and separate parameters to the server without
waiting for the result(s).
</p>
<pre class="synopsis">int PQsendQueryParams(PGconn *conn,
const char *command,
int nParams,
const Oid *paramTypes,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);</pre>
<p>
This is equivalent to <code class="function">PQsendQuery</code> except that
query parameters can be specified separately from the query string.
The function's parameters are handled identically to
<code class="function">PQexecParams</code>. Like
<code class="function">PQexecParams</code>, it will not work on 2.0-protocol
connections, and it allows only one command in the query string.</p>
</dd>
<dt><span class="term"><code class="function">PQsendPrepare</code><a name="id682309"></a></span></dt>
<dd>
<p> Sends a request to create a prepared statement with the given
parameters, without waiting for completion.
</p>
<pre class="synopsis">int PQsendPrepare(PGconn *conn,
const char *stmtName,
const char *query,
int nParams,
const Oid *paramTypes);</pre>
<p>
This is an asynchronous version of <code class="function">PQprepare</code>: it
returns 1 if it was able to dispatch the request, and 0 if not.
After a successful call, call <code class="function">PQgetResult</code>
to determine whether the server successfully created the prepared
statement.
The function's parameters are handled identically to
<code class="function">PQprepare</code>. Like
<code class="function">PQprepare</code>, it will not work on 2.0-protocol
connections.</p>
</dd>
<dt><span class="term"><code class="function">PQsendQueryPrepared</code><a name="id682372"></a></span></dt>
<dd>
<p> Sends a request to execute a prepared statement with given
parameters, without waiting for the result(s).
</p>
<pre class="synopsis">int PQsendQueryPrepared(PGconn *conn,
const char *stmtName,
int nParams,
const char * const *paramValues,
const int *paramLengths,
const int *paramFormats,
int resultFormat);</pre>
<p>
This is similar to <code class="function">PQsendQueryParams</code>, but the
command to be executed is specified by naming a previously-prepared
statement, instead of giving a query string.
The function's parameters are handled identically to
<code class="function">PQexecPrepared</code>. Like
<code class="function">PQexecPrepared</code>, it will not work on 2.0-protocol
connections.</p>
</dd>
<dt><span class="term"><code class="function">PQgetResult</code><a name="id682429"></a></span></dt>
<dd>
<p> Waits for the next result from a prior
<code class="function">PQsendQuery</code>,
<code class="function">PQsendQueryParams</code>,
<code class="function">PQsendPrepare</code>, or
<code class="function">PQsendQueryPrepared</code> call,
and returns it. A null pointer is returned when the command is complete
and there will be no more results.
</p>
<pre class="synopsis">PGresult *PQgetResult(PGconn *conn);</pre>
<p> <code class="function">PQgetResult</code> must be called repeatedly until it returns a null pointer,
indicating that the command is done. (If called when no command is
active, <code class="function">PQgetResult</code> will just return a null pointer at once.)
Each non-null result from <code class="function">PQgetResult</code> should be processed using
the same <code class="structname">PGresult</code> accessor functions previously described.
Don't forget to free each result object with <code class="function">PQclear</code> when done with it.
Note that <code class="function">PQgetResult</code> will block only if a command is active and the
necessary response data has not yet been read by <code class="function">PQconsumeInput</code>.</p>
</dd>
</dl></div>
<p>Using <code class="function">PQsendQuery</code> and <code class="function">PQgetResult</code>
solves one of <code class="function">PQexec</code>'s problems:
If a command string contains multiple <acronym class="acronym">SQL</acronym> commands, the results of those
commands can be obtained individually. (This allows a simple form of
overlapped processing, by the way: the client can be handling the
results of one command while the server is still working on later
queries in the same command string.) However, calling <code class="function">PQgetResult</code> will
still cause the client to block until the server completes the
next <acronym class="acronym">SQL</acronym> command. This can be avoided by proper use of two
more functions:
</p>
<div class="variablelist"><dl>
<dt><span class="term"><code class="function">PQconsumeInput</code><a name="id682584"></a></span></dt>
<dd>
<p> If input is available from the server, consume it.
</p>
<pre class="synopsis">int PQconsumeInput(PGconn *conn);</pre>
<p><code class="function">PQconsumeInput</code> normally returns 1 indicating “<span class="quote">no error</span>”,
but returns 0 if there was some kind of trouble (in which case
<code class="function">PQerrorMessage</code> can be consulted). Note that the result
does not say
whether any input data was actually collected. After calling
<code class="function">PQconsumeInput</code>, the application may check
<code class="function">PQisBusy</code> and/or <code class="function">PQnotifies</code> to see if
their state has changed.</p>
<p><code class="function">PQconsumeInput</code> may be called even if the application is not
prepared to deal with a result or notification just yet. The
function will read available data and save it in a buffer, thereby
causing a <code class="function">select()</code> read-ready indication to go away. The
application can thus use <code class="function">PQconsumeInput</code> to clear the
<code class="function">select()</code> condition immediately, and then examine the results at leisure.</p>
</dd>
<dt><span class="term"><code class="function">PQisBusy</code><a name="id682685"></a></span></dt>
<dd>
<p>Returns 1 if a command is busy, that is, <code class="function">PQgetResult</code> would block
waiting for input. A 0 return indicates that <code class="function">PQgetResult</code> can
be called with assurance of not blocking.
</p>
<pre class="synopsis">int PQisBusy(PGconn *conn);</pre>
<p><code class="function">PQisBusy</code> will not itself attempt to read data from the server;
therefore <code class="function">PQconsumeInput</code> must be invoked first, or the busy
state will never end.</p>
</dd>
</dl></div>
<p>A typical application using these functions will have a main loop that uses
<code class="function">select()</code> or <code class="function">poll()</code> to wait for all the
conditions that it must
respond to. One of the conditions will be input available from the server,
which in terms of <code class="function">select()</code> means readable data on the file
descriptor identified by <code class="function">PQsocket</code>.
When the main loop detects input ready, it should call
<code class="function">PQconsumeInput</code> to read the input. It can then call
<code class="function">PQisBusy</code>, followed by <code class="function">PQgetResult</code>
if <code class="function">PQisBusy</code> returns false (0). It can also call
<code class="function">PQnotifies</code> to detect <code class="command">NOTIFY</code> messages (see <a href="libpq-notify.html" title="28.7.Asynchronous Notification">Section28.7, “Asynchronous Notification”</a>).</p>
<p>A client that uses
<code class="function">PQsendQuery</code>/<code class="function">PQgetResult</code> can
also attempt to cancel a command that is still being processed by the
server; see <a href="libpq-cancel.html" title="28.5.Cancelling Queries in Progress">Section28.5, “Cancelling Queries in Progress”</a>. But regardless of the return value
of <code class="function">PQcancel</code>, the application must continue with the
normal result-reading sequence using <code class="function">PQgetResult</code>.
A successful cancellation will simply cause the command to terminate
sooner than it would have otherwise.</p>
<p>By using the functions described above, it is possible to avoid blocking
while waiting for input from the database server. However, it is still
possible that the application will block waiting to send output to the
server. This is relatively uncommon but can happen if very long SQL commands
or data values are sent. (It is much more probable if the application
sends data via <code class="command">COPY IN</code>, however.) To prevent this possibility and achieve
completely nonblocking database operation, the following additional
functions may be used.
</p>
<div class="variablelist"><dl>
<dt><span class="term"><code class="function">PQsetnonblocking</code><a name="id682886"></a></span></dt>
<dd>
<p> Sets the nonblocking status of the connection.
</p>
<pre class="synopsis">int PQsetnonblocking(PGconn *conn, int arg);</pre>
<p> Sets the state of the connection to nonblocking if
<em class="parameter"><code>arg</code></em> is 1, or
blocking if <em class="parameter"><code>arg</code></em> is 0. Returns 0 if OK, -1 if error.
</p>
<p> In the nonblocking state, calls to
<code class="function">PQsendQuery</code>,
<code class="function">PQputline</code>, <code class="function">PQputnbytes</code>,
and <code class="function">PQendcopy</code>
will not block but instead return an error if they need to be called
again.
</p>
<p> Note that <code class="function">PQexec</code> does not honor nonblocking mode;
if it is called, it will act in blocking fashion anyway.
</p>
</dd>
<dt><span class="term"><code class="function">PQisnonblocking</code><a name="id682970"></a></span></dt>
<dd>
<p> Returns the blocking status of the database connection.
</p>
<pre class="synopsis">int PQisnonblocking(const PGconn *conn);</pre>
<p> Returns 1 if the connection is set to nonblocking mode and
0 if blocking.</p>
</dd>
<dt><span class="term"><code class="function">PQflush</code><a name="id682998"></a></span></dt>
<dd>
<p>Attempts to flush any queued output data to the server.
Returns 0 if successful (or if the send queue is empty), -1 if it failed for
some reason, or 1 if it was unable to send all the data in the send queue yet
(this case can only occur if the connection is nonblocking).
</p>
<pre class="synopsis">int PQflush(PGconn *conn);</pre>
</dd>
</dl></div>
<p>After sending any command or data on a nonblocking connection, call
<code class="function">PQflush</code>. If it returns 1, wait for the socket to be
write-ready and call it again; repeat until it returns 0. Once
<code class="function">PQflush</code> returns 0, wait for the socket to be read-ready
and then read the response as described above.</p>
</div></body>
</html>
|