The PQexec
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:
PQexec
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.
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
.
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
and PQsendQueryPrepared
, which can be used with PQgetResult
to duplicate the functionality of PQexecParams
and PQexecPrepared
respectively.
PQsendQuery
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
may not be called again (on the same connection) until PQgetResult
has returned a null pointer, indicating that the command is done.
PQsendQueryParams
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.
PQsendQueryPrepared
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.
PQgetResult
PQsendQuery
, PQsendQueryParams
, or PQsendQueryPrepared
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
.
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.) However, 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
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 may check PQisBusy
and/or PQnotifies
to see if their state has changed.
PQconsumeInput
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 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
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
Seção 27.6
).
A client that uses PQsendQuery
/PQgetResult
can also attempt to cancel a command that is still being processed by the server.
PQrequestCancel
int PQrequestCancel(PGconn *conn);The return value is 1 if the cancel request was successfully dispatched and 0 if not. (If not,
PQerrorMessage
tells why not.) Successful dispatch is no guarantee that the request will have any effect, however. Regardless of the return value of PQrequestCancel
, the application must continue with the normal result-reading sequence using PQgetResult
. If the cancellation is effective, the current command will terminate early and return an error result. If the cancellation fails (say, because the server was already done processing the command), then there will be no visible result at all.
Note that if the current command is part of a transaction block, cancellation will abort the whole transaction.
PQrequestCancel
can safely be invoked from a signal handler. So, it is also possible to use it in conjunction with plain PQexec
, if the decision to cancel can be made in a signal handler. For example, psql invokes PQrequestCancel
from a SIGINT signal handler, thus allowing interactive cancellation of commands that it issues through PQexec
.
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 may be used.
PQsetnonblocking
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
, 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
int PQisnonblocking(const PGconn *conn);Returns 1 if the connection is set to nonblocking mode and 0 if blocking.
PQflush
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 be write-ready and call it again; repeat until it returns 0. Once PQflush
returns 0, wait for the socket to be read-ready and then read the response as described above.