Обсуждение: postgres fe/be protocol

Поиск
Список
Период
Сортировка

postgres fe/be protocol

От
Chris Bitmead
Дата:
I inserted some debug into libpq, then I ran psql, and I noticed that
there are two 'Z' "Ready for query" messages sent after each query. Is
there a reason for that? Is it a bug?


Re: postgres fe/be protocol

От
Tom Lane
Дата:
Chris Bitmead <chris@bitmead.com> writes:
> I inserted some debug into libpq, then I ran psql, and I noticed that
> there are two 'Z' "Ready for query" messages sent after each query. Is
> there a reason for that? Is it a bug?

I'm pretty sure the backend sends only one 'Z' per query cycle.  Are you
watching the outgoing requests too?  Maybe psql is sending an extra
empty query.  (It didn't use to do that, but maybe it does after Peter's
recent work on it...)
        regards, tom lane


Re: postgres fe/be protocol

От
"Peter Mount"
Дата:
----- Original Message -----
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Chris Bitmead <chris@bitmead.com>
Cc: Postgres Hackers List <hackers@postgresql.org>
Sent: Monday, July 10, 2000 4:44 PM
Subject: Re: [HACKERS] postgres fe/be protocol


> Chris Bitmead <chris@bitmead.com> writes:
> > I inserted some debug into libpq, then I ran psql, and I noticed that
> > there are two 'Z' "Ready for query" messages sent after each query. Is
> > there a reason for that? Is it a bug?
>
> I'm pretty sure the backend sends only one 'Z' per query cycle.  Are you
> watching the outgoing requests too?  Maybe psql is sending an extra
> empty query.  (It didn't use to do that, but maybe it does after Peter's
> recent work on it...)

Actually it used to when it first made a connection to test that it was
alive, but not afterwards. JDBC was originally based on libpq, but I
replaced the empty query with a couple of useful ones.

>
> regards, tom lane



Re: postgres fe/be protocol

От
Chris Bitmead
Дата:
Tom Lane wrote:
> 
> Chris Bitmead <chris@bitmead.com> writes:
> > I inserted some debug into libpq, then I ran psql, and I noticed that
> > there are two 'Z' "Ready for query" messages sent after each query. Is
> > there a reason for that? Is it a bug?
> 
> I'm pretty sure the backend sends only one 'Z' per query cycle.  Are you
> watching the outgoing requests too?  Maybe psql is sending an extra
> empty query.  (It didn't use to do that, but maybe it does after Peter's
> recent work on it...)

I put in a printf in parseInput in fe-exec.c in libpq, straight after it 
reads the id. This is only going to see messages incoming to the front
end.
I also had a break-point on PQexec and it was only called once per
query.
For each query that I input to psql, everything looked normal except
for the two 'Z's.

Ok, I've just done it again on another platform with the same result.
This
is what I see...

chrisb=# select * from a;
P
T
D
C
Z
Zaa  | bb  | cc  
-----+-----+-----aaa | bbb | ccc
(1 row)


We've got the P - select results, T - describe output D - one output
tuple,
C - complete Z - ready for input.

It all seems sensible except for the two Z's.


Re: postgres fe/be protocol

От
Tom Lane
Дата:
Chris Bitmead <chrisb@nimrod.itg.telstra.com.au> writes:
> Tom Lane wrote:
>> I'm pretty sure the backend sends only one 'Z' per query cycle.

> I put in a printf in parseInput in fe-exec.c in libpq, straight after
> it reads the id.

Oh.  What you're missing is that the input message isn't necessarily
*consumed* when first seen.  The sequence of events is

* absorb bufferload of data into libpq input buffer;

* parse messages in parseInput until 'C' is seen;

* when 'C' message is completely read, set asyncStatus = PGASYNC_READY
(fe-exec.c line 756 in current sources), then absorb that message by
advancing inCursor (line 878) and loop back around.  Now it sees the
final 'Z' message, but decides at line 713 not to process it just yet.
So it returns to PQgetResult, which finishes off and stashes away the
PGresult object, and then sets asyncStatus = PGASYNC_BUSY again.

* PQexec will now loop around and call PQgetResult and thence parseInput
again, which will now absorb the 'Z' and set asyncStatus = PGASYNC_IDLE,
which finally allows the PQexec loop to return.  In the meantime your
printf printed the 'Z' a second time.

This is kind of baroque, I agree, but it seemed to be necessary to
support asynchronous data reading without doing too much damage to
backward compatibility of PQexec() semantics.  In particular, the
critical thing here is that we need to be able to deliver a sequence
of PGresult objects when the query string contains multiple commands
and the application is using PQgetResult --- but the old behavior of
PQexec was that you only got back the *last* PGresult if the query
string produced more than one, so I had to preserve that...
        regards, tom lane