34.4. Asynchronous Command Processing
  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:
 
- 
    PQexecwaits 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.) 
- 
    PQexeccan return only onePGresultstructure. If the submitted command string contains multiple SQL commands, all but the lastPGresultare discarded byPQexec.
- 
    PQexecalways collects the command's entire result, buffering it in a singlePGresult. 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 PQerrorMessageto get more information about the failure).int PQsendQuery(PGconn *conn, const char *command); After successfully calling PQsendQuery, callPQgetResultone or more times to obtain the results.PQsendQuerycannot be called again (on the same connection) untilPQgetResulthas returned a null pointer, indicating that the command is done.In pipeline mode, this function is disallowed. 
- 
    
     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 PQsendQueryexcept that query parameters can be specified separately from the query string. The function's parameters are handled identically toPQexecParams. LikePQexecParams, 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, callPQgetResultto determine whether the server successfully created the prepared statement. The function's parameters are handled identically toPQprepare.
- 
    
     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 toPQexecPrepared.
- 
    
     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, callPQgetResultto obtain the results. The function's parameters are handled identically toPQdescribePrepared.
- 
    
     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, callPQgetResultto obtain the results. The function's parameters are handled identically toPQdescribePortal.
- 
    
     PQgetResult
- 
    Waits for the next result from a prior PQsendQuery,PQsendQueryParams,PQsendPrepare,PQsendQueryPrepared,PQsendDescribePrepared,PQsendDescribePortal, orPQpipelineSynccall, and returns it. A null pointer is returned when the command is complete and there will be no more results.PGresult *PQgetResult(PGconn *conn); PQgetResultmust be called repeatedly until it returns a null pointer, indicating that the command is done. (If called when no command is active,PQgetResultwill just return a null pointer at once.) Each non-null result fromPQgetResultshould be processed using the samePGresultaccessor functions previously described. Don't forget to free each result object withPQclearwhen done with it. Note thatPQgetResultwill block only if a command is active and the necessary response data has not yet been read byPQconsumeInput.In pipeline mode, PQgetResultwill return normally unless an error occurs; for any subsequent query sent after the one that caused the error until (and excluding) the next synchronization point, a special result of typePGRES_PIPELINE_ABORTEDwill be returned, and a null pointer will be returned after it. When the pipeline synchronization point is reached, a result of typePGRES_PIPELINE_SYNCwill be returned. The result of the next query after the synchronization point follows immediately (that is, no null pointer is returned after the synchronization point.)NoteEven when PQresultStatusindicates a fatal error,PQgetResultshould 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
  
   Section 34.6
  
  .
 
  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); PQconsumeInputnormally returns 1 indicating " no error " , but returns 0 if there was some kind of trouble (in which casePQerrorMessagecan be consulted). Note that the result does not say whether any input data was actually collected. After callingPQconsumeInput, the application can checkPQisBusyand/orPQnotifiesto see if their state has changed.PQconsumeInputcan 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 aselect()read-ready indication to go away. The application can thus usePQconsumeInputto clear theselect()condition immediately, and then examine the results at leisure.
- 
    
     PQisBusy
- 
    Returns 1 if a command is busy, that is, PQgetResultwould block waiting for input. A 0 return indicates thatPQgetResultcan be called with assurance of not blocking.int PQisBusy(PGconn *conn); PQisBusywill not itself attempt to read data from the server; thereforePQconsumeInputmust 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
  
   Section 34.9
  
  ).
 
  A client that uses
  
   
    PQsendQuery
   
  
  /
  
   
    PQgetResult
   
  
  can also attempt to cancel a command that is still being processed
   by the server; see
  
   Section 34.7
  
  .  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 argis 1, or blocking ifargis 0. Returns 0 if OK, -1 if error.In the nonblocking state, calls to PQsendQuery,PQputline,PQputnbytes,PQputCopyData, andPQendcopywill not block but instead return an error if they need to be called again.Note that PQexecdoes 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.