Re: PQputCopyEnd doesn't adhere to its API contract - Mailing list pgsql-hackers

From Robert Haas
Subject Re: PQputCopyEnd doesn't adhere to its API contract
Date
Msg-id CA+TgmobWtpuX7-zMRuEyMe3+KrVcTEeYbk__rt7P0DwmsXoTHQ@mail.gmail.com
Whole thread Raw
In response to Re: PQputCopyEnd doesn't adhere to its API contract  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: PQputCopyEnd doesn't adhere to its API contract  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
On Thu, May 8, 2014 at 12:09 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> According to the documentation for PQputCopyEnd:
>>> The result is 1 if the termination data was sent, zero if it was not sent because the attempt would block (this
caseis only possible if the connection is in
 
>>> nonblocking mode), or -1 if an error occurred. (Use PQerrorMessage to retrieve details if the return value is -1.
Ifthe value is zero, wait for write-ready and try again.)
 
>
>> However, pqPutCopyEnd contains no return statement that can ever
>> possibly return 0.
>
> IIRC, for some of the libpq functions, the API spec was intended to allow
> for future async behavior that wasn't actually implemented.  So the mere
> fact that it can't return zero today is not a problem.  If it might block
> instead, then we have a problem, but that's not what you're saying.
>
> Also, what the API spec says is that clients should retry PQputCopyEnd
> on a zero return.  We do *not* want them to do that here; once we've
> changed asyncStatus, a retry would report an error.  So the API spec
> in this case is intended to require a retry loop that the current
> implementation doesn't actually need, but that conceivably could be
> needed after some future refactoring.  In particular, we might want
> to fix the code so that it returns zero if it fails to queue the
> COPY END message at all.

Yeah, good point.  I think what confused me is the fact that the
documentation says that when PQputCopyEnd() returns 1, that means that
"the termination data was sent".  So my application sat there and
waited for a server response that never showed up, because in fact the
termination data had *not* been sent.

What I'm now thinking I need to do is something like this:

1. If PQputCopyEnd returns -1, error.
2. while ((rc = PQflush(conn)) != 0) { if (rc < 0) { error; } else {
wait for socket to become read-ready or write-ready; } }
3. while (PQisBusy(conn)) { wait for the socket to become read-ready; }
4. PQgetResult()

Does that sound right?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



pgsql-hackers by date:

Previous
From: Tomas Vondra
Date:
Subject: Re: Sending out a request for more buildfarm animals?
Next
From: Andres Freund
Date:
Subject: A couple logical decoding fixes/patches