Rick Gabriel <klaxian@gmail.com> writes:
> First, I forgot to mention that I am sending async queries (PQsendQuery).
> libpq documentation states that PQgetResult() must be called repeatedly
> until it returns a null pointer.
Right.
> Unfortunately, there is nothing about this
> requirement in the official docs for PHP's libpq wrapper extension.
I think you have grounds to call that a PHP documentation bug. Or at
least it should be made clearer that you also need to read the libpq docs.
> If I
> don't call PQgetResult() one more time than I really need, the transaction
> and connection statuses remain active/busy. Even though PG reports its
> status as "busy", subsequent queries succeed normally.
That's because if you start a new query, libpq will read-and-discard any
remaining server output from the last one. That's not really a good thing
to depend on though --- for example, you might miss an error message that
way.
> I suggest that the connection and transaction states should be updated when
> all queued async queries are completed, without the extra call to
> PQgetResult().
> What do you think?
I think we're not going to change that, because
(a) it's not a bug, it's operating as designed and documented;
(b) this behavior has been stable for more than a dozen years, and
changing it might well break clients expecting the current behavior;
(c) it's not very clear how libpq could do that at all.
I think what you're seeing is related to the fact that the server's
response to a query string involves one or more query results (each
containing some Data messages then a CommandComplete message), followed
by a ReadyForQuery message. PQgetResult will return a PGresult when it's
consumed a CommandComplete message, but you have to call it again to get
libpq to consume the RFQ message --- and it's that message that causes
the PQtransactionStatus result to change. Since RFQ bears the info about
whether the server is truly idle or just idle-in-transaction, libpq cannot
correctly update PQtransactionStatus without reading that message.
You could argue that libpq should "look ahead" after reading
CommandComplete to see if there's an RFQ already received, but I don't
think that could be made to work reliably. You'd either have unwanted
blocking in some cases, or false negatives, anytime the RFQ wasn't
contained in the same TCP packet as the last CC. I doubt people would
want to work with a spec that says "99% of the time PQtransactionStatus
will be updated by the last real PQgetResult call, but sometimes you
need one more call".
regards, tom lane