Thread

  1. Revised proposal for libpq and FE/BE protocol changes

    Tom Lane <tgl@sss.pgh.pa.us> — 1998-04-28T16:21:55Z

    Here is a revised proposal that takes into account the discussions
    of the last few days.  Any comments?
    
    
    I propose to revise libpq and modify the frontend/backend protocol
    to provide the following benefits:
     * Provide a clean way of reading multiple results from a single query
       string.  Among other things, this solves the problem of allowing a
       single query to return several result sets with different descriptors.
     * Allow a frontend to perform other work while awaiting the result of
       a query.
     * Add the ability to cancel queries in progress.
     * Eliminate the need for frontends to issue dummy queries in order
       to detect NOTIFY responses.
     * Eliminate the need for libpq to issue dummy queries internally
       to determine when a query is complete.
    
    We can't break existing code for this, so the behavior of PQexec()
    can't change.  Instead, I propose new functions to add to the API.
    Internally, PQexec will be reimplemented in terms of these new
    functions, but old applications shouldn't notice any difference.
    
    
    The new functions are:
    
    	bool PQsendQuery (PGconn *conn, const char *query);
    
    Submits a query without waiting for the result.  Returns TRUE if the
    query has been successfully dispatched, otherwise FALSE (in the FALSE
    case, an error message is left in conn->errorMessage).
    
    	PGresult* PQgetResult (PGconn *conn);
    
    Waits for input from the backend, and consumes input until (a) a result is
    available, (b) the current query is over, or (c) a copy in/out operation
    is detected.  NULL is returned if the query is over; in all other cases a
    suitable PGresult is returned (which the caller must eventually free).
    Note that no actual "wait" will occur if the necessary input has already
    been consumed; see below.
    
    	bool PQisBusy (PGconn *conn);
    
    Returns TRUE if a query operation is busy (that is, a call to PQgetResult
    would block waiting for more input).  Returns FALSE if PQgetResult would
    return immediately.
    
    	void PQconsumeInput (PGconn *conn);
    
    This can be called at any time to check for and process new input from
    the backend.  It returns no status indication, but after calling it
    the application can use PQisBusy() and/or PQnotifies() to see if a query
    was completed or a NOTIFY message arrived.  This function will never wait
    for more input to arrive.
    
    	int PQsocket (PGconn *conn);
    
    Returns the Unix file descriptor for the socket connection to the backend,
    or -1 if there is no open connection.  This is a violation of modularity,
    of course, but there is no alternative: an application that needs
    asynchronous execution needs to be able to use select() to wait for input
    from either the backend or any other input streams it may have.  To use
    select() the underlying socket must be made visible.
    
    	PGnotify *PQnotifies (PGconn *conn);
    
    This function doesn't change; we just observe that notifications may
    become available as a side effect of executing either PQgetResult() or
    PQconsumeInput(), not just PQexec().
    
    	void PQrequestCancel (PGconn *conn);
    
    Issues a cancel request if possible.  There is no direct way to tell whether
    this has any effect ... see discussion below.
    
    
    Discussion:
    
    An application can continue to use PQexec() as before, and notice
    very little difference in behavior.
    
    Applications that want to be able to handle multiple results from a
    single query should replace PQexec calls with logic like this:
    
    	// Submit the query
    	if (! PQsendQuery(conn, query))
    		reportTheError();
    	// Wait for and process result(s)
    	while ((result = PQgetResult(conn)) != NULL) {
    		switch (PQresultStatus(result)) {
    		... process result, for example:
    		case PGRES_COPY_IN:
    			// ... copy data here ...
    			if (PQendcopy(conn))
    				reportTheError();
    			break;
    		...
    		}
    		PQclear(result);
    	}
    	// When fall out of loop, we're done and ready for a new query
    
    Note that PQgetResult will always report errors by returning a PGresult
    with status PGRES_NONFATAL_ERROR or PGRES_FATAL_ERROR, not by returning
    NULL (since NULL implies non-error termination of the processing loop).
    
    PQexec() will be implemented as follows:
    
    	if (! PQsendQuery(conn, query))
    		return makeEmptyPGresult(conn, PGRES_FATAL_ERROR);
    	lastResult = NULL;
    	while ((result = PQgetResult(conn)) != NULL) {
    		PQclear(lastResult);
    		lastResult = result;
    	}
    	return lastResult;
    
    This maintains the current behavior that the last result of a series
    of commands is returned by PQexec.  (The old implementation is only
    capable of doing that correctly in a limited set of cases, but in the
    cases where it behaves usefully at all, that's how it behaves.)
    
    There is a small difference in behavior, which is that PQexec will now
    return a PGresult with status PGRES_FATAL_ERROR in cases where the old
    implementation would just have returned NULL (and set conn->errorMessage).
    However, any correctly coded application should handle this the same way.
    
    In the above examples, the frontend application is still synchronous: it
    blocks while waiting for the backend to reply to a query.  This is often
    undesirable, since the application may have other work to do, such as
    responding to user input.  Applications can now handle that by using
    PQisBusy and PQconsumeInput along with PQsendQuery and PQgetResult.
    
    The general idea is that the application's main loop will use select()
    to wait for input (from either the backend or its other input sources).
    When select() indicates that input is pending from the backend, the app
    will call PQconsumeInput, followed by checking PQisBusy and/or PQnotifies
    to see what has happened.  If PQisBusy returns FALSE then PQgetResult
    can safely be called to obtain and process a result without blocking.
    
    Note also that NOTIFY messages can arrive asynchronously from the backend.
    They can be detected *without issuing a query* by calling PQconsumeInput
    followed by PQnotifies.  I expect a lot of people will build "partially
    async" applications that detect notifies this way but still do all their
    queries through PQexec (or better, PQsendQuery followed by a synchronous
    PQgetResult loop).  This compromise allows notifies to be detected without
    wasting time by issuing null queries, yet the basic logic of issuing a
    series of queries remains simple.
    
    Finally, since the application can retain control while waiting for a
    query response, it becomes meaningful to try to cancel a query in progress.
    This is done by calling PQrequestCancel().  Note that PQrequestCancel()
    may not have any effect --- if there is no query in progress, or if the
    backend has already finished the query, then it *will* have no effect.
    The application must continue to follow the result-reading protocol after
    issuing a cancel request.  If the cancel is successful, its effect will be
    to cause the current query to fail and return an error message.
    
    
    PROTOCOL CHANGES:
    
    We should change the protocol version number to 2.0.
    It would be possible for the backend to continue to support 1.0 clients,
    if you think it's worth the trouble to do so.
    
    1. New message type:
    
    Command Done
    	Byte1('Z')
    
    The backend will emit this message at completion of processing of every
    command string, just before it resumes waiting for frontend input.
    This change eliminates libpq's current hack of issuing empty queries to
    see whether the backend is done.  Note that 'Z' must be emitted after
    *every* query or function invocation, no matter how it terminated.
    
    2. The RowDescription ('T') message is extended by adding a new value
    for each field.  Just after the type-size value, there will now be
    an int16 "atttypmod" value.  (Would someone provide text specifying
    exactly what this value means?)  libpq will store this value in
    a new "adtmod" field of PGresAttDesc structs.
    
    3. The "Start Copy In" response message is changed from 'D' to 'G',
    and the "Start Copy Out" response message is changed from 'B' to 'H'.
    These changes eliminate potential confusion with the data row messages,
    which also have message codes 'D' and 'B'.
    
    4. The frontend may request cancellation of the current query by sending
    a single byte of OOB (out-of-band) data.  The contents of the data byte
    are irrelevant, since the cancellation will be triggered by the associated
    signal and not by the data itself.  (But we should probably specify that
    the byte be zero, in case we later think of a reason to have different
    kinds of OOB messages.)  There is no specific reply to this message.
    If the backend does cancel a query, the query terminates with an ordinary
    error message indicating that the query was cancelled.
    
    
    			regards, tom lane
    
    
  2. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-04-28T16:42:51Z

    > 2. The RowDescription ('T') message is extended by adding a new value
    > for each field.  Just after the type-size value, there will now be
    > an int16 "atttypmod" value.  (Would someone provide text specifying
    > exactly what this value means?)  libpq will store this value in
    > a new "adtmod" field of PGresAttDesc structs.
    
    >From src/include/catalog/pg_attribute.h:
    
        /*
         * atttypmod records type-specific modifications supplied at table
         * creation time, and passes it to input and output functions as the
         * third argument.
         */
    
    Currently only used for char() and varchar(), and includes a 4-byte
    header.
    
    
    -- 
    Bruce Momjian                          |  830 Blythe Avenue
    maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
      +  If your life is a hard drive,     |  (610) 353-9879(w)
      +  Christ can be your backup.        |  (610) 853-3000(h)
    
    
  3. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    ocie@paracel.com — 1998-04-28T18:03:09Z

    Tom Lane wrote:
    > 
    > Here is a revised proposal that takes into account the discussions
    > of the last few days.  Any comments?
    
    Just one at the end 
    
    [snip]
    
    > 4. The frontend may request cancellation of the current query by sending
    > a single byte of OOB (out-of-band) data.  The contents of the data byte
    > are irrelevant, since the cancellation will be triggered by the associated
    > signal and not by the data itself.  (But we should probably specify that
    > the byte be zero, in case we later think of a reason to have different
    > kinds of OOB messages.)  There is no specific reply to this message.
    > If the backend does cancel a query, the query terminates with an ordinary
    > error message indicating that the query was cancelled.
    
    You didn't come right out and say it, but are you intending to support
    multiple queries within a connection?  I gather not.  Not that I'm
    suggesting that this be done, as it seems this would complicate the
    user's application and the backend.  With only one possible OOB
    message, you can't tell it which query to cancel.
    
    Ocie Mitchell
    
    
  4. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    David Gould <dg@illustra.com> — 1998-04-29T05:32:33Z

    > 
    > Tom Lane wrote:
    > > 
    > > Here is a revised proposal that takes into account the discussions
    > > of the last few days.  Any comments?
    > 
    > Just one at the end 
    > 
    > [snip]
    > 
    > > 4. The frontend may request cancellation of the current query by sending
    > > a single byte of OOB (out-of-band) data.  The contents of the data byte
    > > are irrelevant, since the cancellation will be triggered by the associated
    > > signal and not by the data itself.  (But we should probably specify that
    > > the byte be zero, in case we later think of a reason to have different
    > > kinds of OOB messages.)  There is no specific reply to this message.
    > > If the backend does cancel a query, the query terminates with an ordinary
    > > error message indicating that the query was cancelled.
    > 
    > You didn't come right out and say it, but are you intending to support
    > multiple queries within a connection?  I gather not.  Not that I'm
    > suggesting that this be done, as it seems this would complicate the
    > user's application and the backend.  With only one possible OOB
    > message, you can't tell it which query to cancel.
    > 
    > Ocie Mitchell
    
    Waves hand wildly... I know, I know!
    
       All of them!
    
    -dg
    
    David Gould            dg@illustra.com           510.628.3783 or 510.305.9468 
    Informix Software  (No, really)         300 Lakeside Drive  Oakland, CA 94612
    "(Windows NT) version 5.0 will build on a proven system architecture
     and incorporate tens of thousands of bug fixes from version 4.0."
                     -- <http://www.microsoft.com/y2k.asp?A=7&B=5>
    
    
  5. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Michael Meskes <meskes@topsystem.de> — 1998-04-29T08:35:31Z

    Tom Lane writes:
    > I propose to revise libpq and modify the frontend/backend protocol
    > to provide the following benefits:
    >  * Provide a clean way of reading multiple results from a single query
    >    string.  Among other things, this solves the problem of allowing a
    >    single query to return several result sets with different descriptors.
    
    Does this mean I can read in a complete C array with one call? I mean
    something like this:
    
    char emp_name[10][10];
    
    exec sql select name into :emp_name from emp;
    
    But then I didn't see anything like this in your examples. Do I have to
    iterate using PQgetResult then?
    
    Michael
    -- 
    Dr. Michael Meskes, Project-Manager    | topsystem Systemhaus GmbH
    meskes@topsystem.de                    | Europark A2, Adenauerstr. 20
    meskes@debian.org                      | 52146 Wuerselen
    Go SF49ers! Go Rhein Fire!             | Tel: (+49) 2405/4670-44
    Use Debian GNU/Linux!                  | Fax: (+49) 2405/4670-10
    
    
  6. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Phil Thompson <phil@river-bank.demon.co.uk> — 1998-04-29T21:07:53Z

    Tom Lane wrote:
    > 
    > PROTOCOL CHANGES:
    > 
    > We should change the protocol version number to 2.0.
    > It would be possible for the backend to continue to support 1.0 clients,
    > if you think it's worth the trouble to do so.
    
    Or 1.1?  The changes don't seem too traumatic.  Either way, maintaining
    support for 1.0 is important as not all of us use libpq and we need time
    to catch up.  Also we don't want to put barriers in the way of companies
    like Openlink who seem willing to provide support for PostgreSQL in
    commercial products.
    
    > 1. New message type:
    > 
    > Command Done
    >         Byte1('Z')
    > 
    > The backend will emit this message at completion of processing of every
    > command string, just before it resumes waiting for frontend input.
    > This change eliminates libpq's current hack of issuing empty queries to
    > see whether the backend is done.  Note that 'Z' must be emitted after
    > *every* query or function invocation, no matter how it terminated.
    
    The completion response already does this for successful queries, and
    the error response for unsuccessful ones.  I came to the conclusion (but
    not with absolute certainty) a while back that the empty query hack was
    needed for an old feature of the backend that is no longer there.  From
    looking at a dump of the data between psql and the backend for 6.3.2 I
    don't think that those empty queries are issued any more.  I have
    implemented a pure Tcl frontend that doesn't issue them and I haven't
    seen any problems.
    
    The exception to the above is the single empty query sent immediately
    after the frontend has been successfully authenticated.  This is useful
    because it has the side effect of checking that the user has privileges
    against the particular database - it is better to do this as part of the
    session set up rather than the first real query which may be some time
    later.
    
    > 3. The "Start Copy In" response message is changed from 'D' to 'G',
    > and the "Start Copy Out" response message is changed from 'B' to 'H'.
    > These changes eliminate potential confusion with the data row messages,
    > which also have message codes 'D' and 'B'.
    
    The context means there should be no confusion - but if the protocol is
    being changed anyway then it makes sense to do this.
    
    Phil
    
    
  7. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-04-29T23:03:18Z

    > 
    > Tom Lane wrote:
    > > 
    > > PROTOCOL CHANGES:
    > > 
    > > We should change the protocol version number to 2.0.
    > > It would be possible for the backend to continue to support 1.0 clients,
    > > if you think it's worth the trouble to do so.
    > 
    > Or 1.1?  The changes don't seem too traumatic.  Either way, maintaining
    > support for 1.0 is important as not all of us use libpq and we need time
    > to catch up.  Also we don't want to put barriers in the way of companies
    > like Openlink who seem willing to provide support for PostgreSQL in
    > commercial products.
    
    Yes, but there will be a month for people to get their third-part stuff
    changed, and the changes are pretty straight-forward.  Having support
    for both in the backend/frontend is going to make that code more
    difficult.
    
    If it was only a small change, we could keep it compatable, but it seems
    it would be best to just announce it early on.  People can start testing
    their new drivers long before the beta period begins.
    
    Also, we are making this change well in advance of the beta, so I hope
    they would have enough time to make the transition.
    
    > > The backend will emit this message at completion of processing of every
    > > command string, just before it resumes waiting for frontend input.
    > > This change eliminates libpq's current hack of issuing empty queries to
    > > see whether the backend is done.  Note that 'Z' must be emitted after
    > > *every* query or function invocation, no matter how it terminated.
    > 
    > The completion response already does this for successful queries, and
    > the error response for unsuccessful ones.  I came to the conclusion (but
    > not with absolute certainty) a while back that the empty query hack was
    > needed for an old feature of the backend that is no longer there.  From
    > looking at a dump of the data between psql and the backend for 6.3.2 I
    > don't think that those empty queries are issued any more.  I have
    > implemented a pure Tcl frontend that doesn't issue them and I haven't
    > seen any problems.
    > 
    > The exception to the above is the single empty query sent immediately
    > after the frontend has been successfully authenticated.  This is useful
    > because it has the side effect of checking that the user has privileges
    > against the particular database - it is better to do this as part of the
    > session set up rather than the first real query which may be some time
    > later.
    
    Good insight on the libpq interface.  I think we need the new return
    code because of the possibility of multiple results from the backend. 
    In the old code, without the empty query, doesn't a query with multiple
    statements cause the send/return results to get out of sync.
    
    > > 3. The "Start Copy In" response message is changed from 'D' to 'G',
    > > and the "Start Copy Out" response message is changed from 'B' to 'H'.
    > > These changes eliminate potential confusion with the data row messages,
    > > which also have message codes 'D' and 'B'.
    > 
    > The context means there should be no confusion - but if the protocol is
    > being changed anyway then it makes sense to do this.
    
    
    -- 
    Bruce Momjian                          |  830 Blythe Avenue
    maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
      +  If your life is a hard drive,     |  (610) 353-9879(w)
      +  Christ can be your backup.        |  (610) 853-3000(h)
    
    
  8. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Phil Thompson <phil@river-bank.demon.co.uk> — 1998-04-30T18:33:43Z

    Bruce Momjian wrote:
    
    > > Either way, maintaining
    > > support for 1.0 is important as not all of us use libpq and we need time
    > > to catch up.  Also we don't want to put barriers in the way of companies
    > > like Openlink who seem willing to provide support for PostgreSQL in
    > > commercial products.
    > 
    > Yes, but there will be a month for people to get their third-part stuff
    > changed, and the changes are pretty straight-forward.  Having support
    > for both in the backend/frontend is going to make that code more
    > difficult.
    
    I agree it will be easy enough for most of us, but may be less so for
    companies that traditionally don't release often.  Although I don't use
    Openlink's software and can't comment on whether it's any good (or if
    anybody actually uses it), I take it as a compliment to PostgreSQL that
    a commercial organisation is willing to provide some support for it. 
    Not maintaining backwards compatibility for at least some time isn't
    going to encourage them to continue that support.
    
    Phil
    
    
  9. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    David Gould <dg@illustra.com> — 1998-05-22T07:00:02Z

    Bruce Momjian wrote: 
    > > 
    > > Tom Lane wrote:
    > > > 
    > > > PROTOCOL CHANGES:
    > > > 
    > > > We should change the protocol version number to 2.0.
    > > > It would be possible for the backend to continue to support 1.0 clients,
    > > > if you think it's worth the trouble to do so.
    > > 
    > > Or 1.1?  The changes don't seem too traumatic.  Either way, maintaining
    > > support for 1.0 is important as not all of us use libpq and we need time
    > > to catch up.  Also we don't want to put barriers in the way of companies
    > > like Openlink who seem willing to provide support for PostgreSQL in
    > > commercial products.
    > 
    > Yes, but there will be a month for people to get their third-part stuff
    > changed, and the changes are pretty straight-forward.  Having support
    > for both in the backend/frontend is going to make that code more
    > difficult.
    > 
    > If it was only a small change, we could keep it compatable, but it seems
    > it would be best to just announce it early on.  People can start testing
    > their new drivers long before the beta period begins.
    > 
    > Also, we are making this change well in advance of the beta, so I hope
    > they would have enough time to make the transition.
    
    I know this is old old discussion, so "shut up, we're done with it" is a
    fine answer...
    
    But, I think maintaining compatibility with 1.0 is important. If we expect
    people to really use this software to build real applications, then we
    cannot expect them to be interested in revising or even recompiling their
    applications.
    
    For example a web development consulting house. They build shopping cart
    or other database using web sites for their clients.  They do not want to
    have to go to each of their customers (say hundreds of sites) and recompile
    everything just to take advantage of a new server that happens to fix some
    bugs they needed fixed. They also don't want to reload the databases or
    otherwise get involved in upgrade issues. And, their clients don't want
    to pay for this either.
    
    Database customers at least in the commercial world can be incredibly
    conservative. It is not at all uncommon to have large sites running DBMS
    engines that are three major releases (ie, well over three years) old.
    Once they get an app working, they really don't want anything to change.
    
    -dg
    
    David Gould            dg@illustra.com           510.628.3783 or 510.305.9468 
    Informix Software  (No, really)         300 Lakeside Drive  Oakland, CA 94612
    "Of course, someone who knows more about this will correct me if I'm wrong,
     and someone who knows less will correct me if I'm right."
                   --David Palmer (palmer@tybalt.caltech.edu)
    
    
  10. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-05-22T14:16:03Z

    > Database customers at least in the commercial world can be incredibly
    > conservative. It is not at all uncommon to have large sites running DBMS
    > engines that are three major releases (ie, well over three years) old.
    > Once they get an app working, they really don't want anything to change.
    
    Yes, this is true.  Their data is locked in Our database.  And you can't
    just restart it like a PC OS or word processor.  Database demands are
    much different.
    
    -- 
    Bruce Momjian                          |  830 Blythe Avenue
    maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
      +  If your life is a hard drive,     |  (610) 353-9879(w)
      +  Christ can be your backup.        |  (610) 853-3000(h)
    
    
  11. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-05-22T14:16:49Z

    > Database customers at least in the commercial world can be incredibly
    > conservative. It is not at all uncommon to have large sites running DBMS
    > engines that are three major releases (ie, well over three years) old.
    > Once they get an app working, they really don't want anything to change.
    
    And, oh yea, we kept database compatability, thanks to Tom Lane.
    
    -- 
    Bruce Momjian                          |  830 Blythe Avenue
    maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
      +  If your life is a hard drive,     |  (610) 353-9879(w)
      +  Christ can be your backup.        |  (610) 853-3000(h)
    
    
  12. Re: [HACKERS] Revised proposal for libpq and FE/BE protocol changes

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-07-05T00:05:25Z

    Tom, just wondering were we are with this.  Can you update libpq.3?  I
    think until the sgml of the manual is converted, they are the most
    current.  I just made some cleanups there myself.  Are the sgml sources
    updated with the protocol changes?
    
    Also, are these items completed?  How about our cancel query key?  I
    think it is random/secure enough for our purposes.  Can you make the
    changes, or do you need changes from me?
    
    ---------------------------------------------------------------------------
    
    
    > Here is a revised proposal that takes into account the discussions
    > of the last few days.  Any comments?
    > 
    > 
    > I propose to revise libpq and modify the frontend/backend protocol
    > to provide the following benefits:
    >  * Provide a clean way of reading multiple results from a single query
    >    string.  Among other things, this solves the problem of allowing a
    >    single query to return several result sets with different descriptors.
    >  * Allow a frontend to perform other work while awaiting the result of
    >    a query.
    >  * Add the ability to cancel queries in progress.
    >  * Eliminate the need for frontends to issue dummy queries in order
    >    to detect NOTIFY responses.
    >  * Eliminate the need for libpq to issue dummy queries internally
    >    to determine when a query is complete.
    > 
    > We can't break existing code for this, so the behavior of PQexec()
    > can't change.  Instead, I propose new functions to add to the API.
    > Internally, PQexec will be reimplemented in terms of these new
    > functions, but old applications shouldn't notice any difference.
    > 
    > 
    > The new functions are:
    > 
    > 	bool PQsendQuery (PGconn *conn, const char *query);
    > 
    > Submits a query without waiting for the result.  Returns TRUE if the
    > query has been successfully dispatched, otherwise FALSE (in the FALSE
    > case, an error message is left in conn->errorMessage).
    > 
    > 	PGresult* PQgetResult (PGconn *conn);
    > 
    > Waits for input from the backend, and consumes input until (a) a result is
    > available, (b) the current query is over, or (c) a copy in/out operation
    > is detected.  NULL is returned if the query is over; in all other cases a
    > suitable PGresult is returned (which the caller must eventually free).
    > Note that no actual "wait" will occur if the necessary input has already
    > been consumed; see below.
    > 
    > 	bool PQisBusy (PGconn *conn);
    > 
    > Returns TRUE if a query operation is busy (that is, a call to PQgetResult
    > would block waiting for more input).  Returns FALSE if PQgetResult would
    > return immediately.
    > 
    > 	void PQconsumeInput (PGconn *conn);
    > 
    > This can be called at any time to check for and process new input from
    > the backend.  It returns no status indication, but after calling it
    > the application can use PQisBusy() and/or PQnotifies() to see if a query
    > was completed or a NOTIFY message arrived.  This function will never wait
    > for more input to arrive.
    > 
    > 	int PQsocket (PGconn *conn);
    > 
    > Returns the Unix file descriptor for the socket connection to the backend,
    > or -1 if there is no open connection.  This is a violation of modularity,
    > of course, but there is no alternative: an application that needs
    > asynchronous execution needs to be able to use select() to wait for input
    > from either the backend or any other input streams it may have.  To use
    > select() the underlying socket must be made visible.
    > 
    > 	PGnotify *PQnotifies (PGconn *conn);
    > 
    > This function doesn't change; we just observe that notifications may
    > become available as a side effect of executing either PQgetResult() or
    > PQconsumeInput(), not just PQexec().
    > 
    > 	void PQrequestCancel (PGconn *conn);
    > 
    > Issues a cancel request if possible.  There is no direct way to tell whether
    > this has any effect ... see discussion below.
    > 
    > 
    > Discussion:
    > 
    > An application can continue to use PQexec() as before, and notice
    > very little difference in behavior.
    > 
    > Applications that want to be able to handle multiple results from a
    > single query should replace PQexec calls with logic like this:
    > 
    > 	// Submit the query
    > 	if (! PQsendQuery(conn, query))
    > 		reportTheError();
    > 	// Wait for and process result(s)
    > 	while ((result = PQgetResult(conn)) != NULL) {
    > 		switch (PQresultStatus(result)) {
    > 		... process result, for example:
    > 		case PGRES_COPY_IN:
    > 			// ... copy data here ...
    > 			if (PQendcopy(conn))
    > 				reportTheError();
    > 			break;
    > 		...
    > 		}
    > 		PQclear(result);
    > 	}
    > 	// When fall out of loop, we're done and ready for a new query
    > 
    > Note that PQgetResult will always report errors by returning a PGresult
    > with status PGRES_NONFATAL_ERROR or PGRES_FATAL_ERROR, not by returning
    > NULL (since NULL implies non-error termination of the processing loop).
    > 
    > PQexec() will be implemented as follows:
    > 
    > 	if (! PQsendQuery(conn, query))
    > 		return makeEmptyPGresult(conn, PGRES_FATAL_ERROR);
    > 	lastResult = NULL;
    > 	while ((result = PQgetResult(conn)) != NULL) {
    > 		PQclear(lastResult);
    > 		lastResult = result;
    > 	}
    > 	return lastResult;
    > 
    > This maintains the current behavior that the last result of a series
    > of commands is returned by PQexec.  (The old implementation is only
    > capable of doing that correctly in a limited set of cases, but in the
    > cases where it behaves usefully at all, that's how it behaves.)
    > 
    > There is a small difference in behavior, which is that PQexec will now
    > return a PGresult with status PGRES_FATAL_ERROR in cases where the old
    > implementation would just have returned NULL (and set conn->errorMessage).
    > However, any correctly coded application should handle this the same way.
    > 
    > In the above examples, the frontend application is still synchronous: it
    > blocks while waiting for the backend to reply to a query.  This is often
    > undesirable, since the application may have other work to do, such as
    > responding to user input.  Applications can now handle that by using
    > PQisBusy and PQconsumeInput along with PQsendQuery and PQgetResult.
    > 
    > The general idea is that the application's main loop will use select()
    > to wait for input (from either the backend or its other input sources).
    > When select() indicates that input is pending from the backend, the app
    > will call PQconsumeInput, followed by checking PQisBusy and/or PQnotifies
    > to see what has happened.  If PQisBusy returns FALSE then PQgetResult
    > can safely be called to obtain and process a result without blocking.
    > 
    > Note also that NOTIFY messages can arrive asynchronously from the backend.
    > They can be detected *without issuing a query* by calling PQconsumeInput
    > followed by PQnotifies.  I expect a lot of people will build "partially
    > async" applications that detect notifies this way but still do all their
    > queries through PQexec (or better, PQsendQuery followed by a synchronous
    > PQgetResult loop).  This compromise allows notifies to be detected without
    > wasting time by issuing null queries, yet the basic logic of issuing a
    > series of queries remains simple.
    > 
    > Finally, since the application can retain control while waiting for a
    > query response, it becomes meaningful to try to cancel a query in progress.
    > This is done by calling PQrequestCancel().  Note that PQrequestCancel()
    > may not have any effect --- if there is no query in progress, or if the
    > backend has already finished the query, then it *will* have no effect.
    > The application must continue to follow the result-reading protocol after
    > issuing a cancel request.  If the cancel is successful, its effect will be
    > to cause the current query to fail and return an error message.
    > 
    > 
    > PROTOCOL CHANGES:
    > 
    > We should change the protocol version number to 2.0.
    > It would be possible for the backend to continue to support 1.0 clients,
    > if you think it's worth the trouble to do so.
    > 
    > 1. New message type:
    > 
    > Command Done
    > 	Byte1('Z')
    > 
    > The backend will emit this message at completion of processing of every
    > command string, just before it resumes waiting for frontend input.
    > This change eliminates libpq's current hack of issuing empty queries to
    > see whether the backend is done.  Note that 'Z' must be emitted after
    > *every* query or function invocation, no matter how it terminated.
    > 
    > 2. The RowDescription ('T') message is extended by adding a new value
    > for each field.  Just after the type-size value, there will now be
    > an int16 "atttypmod" value.  (Would someone provide text specifying
    > exactly what this value means?)  libpq will store this value in
    > a new "adtmod" field of PGresAttDesc structs.
    > 
    > 3. The "Start Copy In" response message is changed from 'D' to 'G',
    > and the "Start Copy Out" response message is changed from 'B' to 'H'.
    > These changes eliminate potential confusion with the data row messages,
    > which also have message codes 'D' and 'B'.
    > 
    > 4. The frontend may request cancellation of the current query by sending
    > a single byte of OOB (out-of-band) data.  The contents of the data byte
    > are irrelevant, since the cancellation will be triggered by the associated
    > signal and not by the data itself.  (But we should probably specify that
    > the byte be zero, in case we later think of a reason to have different
    > kinds of OOB messages.)  There is no specific reply to this message.
    > If the backend does cancel a query, the query terminates with an ordinary
    > error message indicating that the query was cancelled.
    
    
    -- 
    Bruce Momjian                          |  830 Blythe Avenue
    maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
      +  If your life is a hard drive,     |  (610) 353-9879(w)
      +  Christ can be your backup.        |  (610) 853-3000(h)