Asynchronous Query Processing

The PQexec function is adequate for submitting queries in simple synchronous applications. However, it has a couple of major deficiencies:

Older programs that used this functionality as well as PQputline and PQputnbytes could block waiting to send data to the backend. To address that issue, the function PQsetnonblocking was added.

Old applications can neglect to use PQsetnonblocking and get the older potentially blocking behavior. Newer programs can use PQsetnonblocking to achieve a completely non-blocking connection to the backend.

Asynchronous Query Functions

PQsetnonblocking

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 TRUE, blocking if arg is FALSE. Returns 0 if OK, -1 if error.

In the nonblocking state, calls to PQputline, PQputnbytes, PQsendQuery and PQendcopy will not block, but instead return an error if they need to be called again.

When a database connection has been set to non-blocking mode and PQexec is called, it will temporarily set the state of the connection to blocking until the PQexec completes.

More of libpq is expected to be made safe for PQsetnonblocking functionality in the near future.

PQisnonblocking

PQisnonblocking returns the blocking status of the database connection.
int PQisnonblocking(const PGconn *conn)
Returns TRUE if the connection is set to non-blocking mode, FALSE if blocking.

PQsendQuery

PQsendQuery submits a query to the backend server without waiting for the results. TRUE is returned if the query was successfully dispatched, FALSE if not (in which case, use PQerrorMessage to get more information about the failure).
int PQsendQuery(PGconn *conn, const char *query);
After successfully calling PQsendQuery, call PQgetResult one or more times to obtain the query results. PQsendQuery may not be called again (on the same connection) until PQgetResult has returned NULL, indicating that the query is done.

PQgetResult

PQgetResult waits for the next result from a prior PQsendQuery, and returns it. NULL is returned when the query is complete and there will be no more results.
PGresult *PQgetResult(PGconn *conn);
PQgetResult must be called repeatedly until it returns NULL, indicating that the query is done. (If called when no query is active, PQgetResult returns NULL immediately.) Process each non-NULL result from PQgetResult by using the same PGresult accessor functions previously described. Free each result object with PQclear when done with it. Note that PQgetResult will block only if a query 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 query string contains multiple SQL commands, the results of those commands can be obtained individually. (This allows a simple form of overlapped processing as the frontend can be handling the results of one query while the backend is still working on later queries in the same query string.) However, calling PQgetResult will still cause the frontend to block until the backend completes the next SQL command. This can be avoided by proper use of the functions described below:

PQconsumeInput

PQconsumeInput consumes any input available from the backend.
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 is set). 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 its state has changed.

PQconsumeInput may be called even if the application is not prepared to deal with a result or notification just yet. The routine will read available data and save it in a buffer, thereby causing a select(2) 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

PQisBusy returns 1 if a query 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 read data from the backend; PQconsumeInput must be invoked first, or the busy state will never end.

PQflush

PQflush attempts to flush any data queued to the backend. Returns 0 if successful (or if the sent queue is empty) or EOF if it failed.
int PQflush(PGconn *conn);
PQflush needs to be called on a non-blocking connection before calling select to determine if a response has arrived. If 0 is returned it ensures that there is no data queued to the backend that has not actually been sent. Only applications that have used PQsetnonblocking require this.

PQsocket

PQsocket obtains the file descriptor number for the backend connection socket. A valid descriptor will be >= 0; a result of -1 indicates that no backend connection is currently open.
int PQsocket(const PGconn *conn);
Use PQsocket to obtain the backend socket descriptor in preparation for executing select(). This allows an application using a blocking connection to wait for either backend responses or other conditions. If the result of select() indicates that data can be read from the backend socket, then PQconsumeInput should be called to read the data; after which, PQisBusy, PQgetResult, and/or PQnotifies can be used to process the response.

Non-blocking connections (that have used PQsetnonblocking) should not use select until PQflush has returned 0 indicating that there is no buffered data waiting to be sent to the backend.

A typical frontend using these functions will have a main loop that uses select() to wait for all the conditions that it must respond to. One of the conditions will be input available from the backend, which in select's terms is 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 the Section called Asynchronous Notification).

A frontend that uses PQsendQuery/PQgetResult can also attempt to cancel a query that is still being processed by the backend.

PQrequestCancel

PQrequestCancel requests that PostgreSQL abandon processing of the current query.
int PQrequestCancel(PGconn *conn);
The return value is 1 if the cancel request was successfully dispatched, 0 if not. (If not, PQerrorMessage tells why not.) Successful dispatch does 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 query will terminate early and return an error result. If the cancellation fails (say, because the backend was already done processing the query), then there will be no visible result.

Note that if the current query is part of a transaction, 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 queries that it issues through PQexec. Note that PQrequestCancel will have no effect if the connection is not currently open or the backend is not currently processing a query.