The PQexec
function is adequate for submitting
commands in normal, synchronous applications. It has a few
deficiencies, however, that can be of importance to some users:
PQexec
waits for the command to be completed.
The application might have other work to do (such as maintaining a
user interface), in which case it won't want to block waiting for
the response.
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.)
PQexec
can return only one
PGresult
structure. If the submitted command
string contains multiple SQL commands, all but
the last PGresult
are discarded by
PQexec
.
PQexec
always collects the command's entire result,
buffering it in a single PGresult
. While
this simplifies error-handling logic for the application, it can be
impractical for results containing many rows.
Applications that do not like these limitations can instead use the
underlying functions that PQexec
is built from:
PQsendQuery
and PQgetResult
.
There are also
PQsendQueryParams
,
PQsendPrepare
,
PQsendQueryPrepared
,
PQsendDescribePrepared
, and
PQsendDescribePortal
,
which can be used with PQgetResult
to duplicate
the functionality of
PQexecParams
,
PQprepare
,
PQexecPrepared
,
PQdescribePrepared
, and
PQdescribePortal
respectively.
PQsendQuery
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 PQerrorMessage
to get more
information about the failure).
int PQsendQuery(PGconn *conn, const char *command);
After successfully calling PQsendQuery
, call
PQgetResult
one or more times to obtain the
results. PQsendQuery
cannot be called again
(on the same connection) until PQgetResult
has returned a null pointer, indicating that the command is done.
PQsendQueryParams
Submits a command and separate parameters to the server without waiting for the result(s).
int PQsendQueryParams(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
This is equivalent to PQsendQuery
except that
query parameters can be specified separately from the query string.
The function's parameters are handled identically to
PQexecParams
. Like
PQexecParams
, it will not work on 2.0-protocol
connections, and it allows only one command in the query string.
PQsendPrepare
Sends a request to create a prepared statement with the given parameters, without waiting for completion.
int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes);
This is an asynchronous version of PQprepare
: it
returns 1 if it was able to dispatch the request, and 0 if not.
After a successful call, call PQgetResult
to
determine whether the server successfully created the prepared
statement. The function's parameters are handled identically to
PQprepare
. Like
PQprepare
, it will not work on 2.0-protocol
connections.
PQsendQueryPrepared
Sends a request to execute a prepared statement with given parameters, without waiting for the result(s).
int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, int resultFormat);
This is similar to PQsendQueryParams
, 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
PQexecPrepared
. Like
PQexecPrepared
, it will not work on
2.0-protocol connections.
PQsendDescribePrepared
Submits a request to obtain information about the specified prepared statement, without waiting for completion.
int PQsendDescribePrepared(PGconn *conn, const char *stmtName);
This is an asynchronous version of PQdescribePrepared
:
it returns 1 if it was able to dispatch the request, and 0 if not.
After a successful call, call PQgetResult
to
obtain the results. The function's parameters are handled
identically to PQdescribePrepared
. Like
PQdescribePrepared
, it will not work on
2.0-protocol connections.
PQsendDescribePortal
Submits a request to obtain information about the specified portal, without waiting for completion.
int PQsendDescribePortal(PGconn *conn, const char *portalName);
This is an asynchronous version of PQdescribePortal
:
it returns 1 if it was able to dispatch the request, and 0 if not.
After a successful call, call PQgetResult
to
obtain the results. The function's parameters are handled
identically to PQdescribePortal
. Like
PQdescribePortal
, it will not work on
2.0-protocol connections.
PQgetResult
Waits for the next result from a prior
PQsendQuery
,
PQsendQueryParams
,
PQsendPrepare
,
PQsendQueryPrepared
,
PQsendDescribePrepared
, or
PQsendDescribePortal
call, and returns it.
A null pointer is returned when the command is complete and there
will be no more results.
PGresult *PQgetResult(PGconn *conn);
PQgetResult
must be called repeatedly until
it returns a null pointer, indicating that the command is done.
(If called when no command is active,
PQgetResult
will just return a null pointer
at once.) Each non-null result from
PQgetResult
should be processed using the
same PGresult
accessor functions previously
described. Don't forget to free each result object with
PQclear
when done with it. Note that
PQgetResult
will block only if a command is
active and the necessary response data has not yet been read by
PQconsumeInput
.
Even when PQresultStatus
indicates a fatal
error, PQgetResult
should be called until it
returns a null pointer, to allow libpq to
process the error information completely.
Using PQsendQuery
and
PQgetResult
solves one of
PQexec
's problems: If a command string contains
multiple SQL 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.)
Another frequently-desired feature that can be obtained with
PQsendQuery
and PQgetResult
is retrieving large query results a row at a time. This is discussed
in 33.5절.
By itself, calling PQgetResult
will still cause the client to block until the server completes the
next SQL command. This can be avoided by proper
use of two more functions:
PQconsumeInput
If input is available from the server, consume it.
int PQconsumeInput(PGconn *conn);
PQconsumeInput
normally returns 1 indicating
“no error”, but returns 0 if there was some kind of
trouble (in which case PQerrorMessage
can be
consulted). Note that the result does not say whether any input
data was actually collected. After calling
PQconsumeInput
, the application can check
PQisBusy
and/or
PQnotifies
to see if their state has changed.
PQconsumeInput
can 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 select()
read-ready indication to go away. The application can thus use
PQconsumeInput
to clear the
select()
condition immediately, and then
examine the results at leisure.
PQisBusy
Returns 1 if a command is busy, that is,
PQgetResult
would block waiting for input.
A 0 return indicates that PQgetResult
can be
called with assurance of not blocking.
int PQisBusy(PGconn *conn);
PQisBusy
will not itself attempt to read data
from the server; therefore PQconsumeInput
must be invoked first, or the busy state will never end.
A typical application using these functions will have a main loop that
uses select()
or poll()
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
select()
means readable data on the file
descriptor identified by PQsocket
. When the main
loop detects input ready, it should call
PQconsumeInput
to read the input. It can then
call PQisBusy
, followed by
PQgetResult
if PQisBusy
returns false (0). It can also call PQnotifies
to detect NOTIFY
messages (see 33.8절).
A client that uses
PQsendQuery
/PQgetResult
can also attempt to cancel a command that is still being processed
by the server; see 33.6절. But regardless of
the return value of PQcancel
, the application
must continue with the normal result-reading sequence using
PQgetResult
. A successful cancellation will
simply cause the command to terminate sooner than it would have
otherwise.
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 COPY IN
,
however.) To prevent this possibility and achieve completely
nonblocking database operation, the following additional functions
can be used.
PQsetnonblocking
Sets the nonblocking status of the connection.
int PQsetnonblocking(PGconn *conn, int arg);
Sets the state of the connection to nonblocking if
arg
is 1, or blocking if
arg
is 0. Returns 0 if OK, -1 if error.
In the nonblocking state, calls to
PQsendQuery
, PQputline
,
PQputnbytes
, PQputCopyData
,
and PQendcopy
will not block but instead return
an error if they need to be called again.
Note that PQexec
does not honor nonblocking
mode; if it is called, it will act in blocking fashion anyway.
PQisnonblocking
Returns the blocking status of the database connection.
int PQisnonblocking(const PGconn *conn);
Returns 1 if the connection is set to nonblocking mode and 0 if blocking.
PQflush
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).
int PQflush(PGconn *conn);
After sending any command or data on a nonblocking connection, call
PQflush
. If it returns 1, wait for the socket
to become read- or write-ready. If it becomes write-ready, call
PQflush
again. If it becomes read-ready, call
PQconsumeInput
, then call
PQflush
again. Repeat until
PQflush
returns 0. (It is necessary to check for
read-ready and drain the input with PQconsumeInput
,
because the server can block trying to send us data, e.g., NOTICE
messages, and won't read our data until we read its.) Once
PQflush
returns 0, wait for the socket to be
read-ready and then read the response as described above.