Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 16503e6

Browse files
committed
Extended query protocol: parse, bind, execute, describe FE/BE messages.
Only lightly tested as yet, since libpq doesn't know anything about 'em.
1 parent a59793f commit 16503e6

File tree

17 files changed

+1329
-261
lines changed

17 files changed

+1329
-261
lines changed

doc/src/sgml/protocol.sgml

+74-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.33 2003/04/28 05:17:31 tgl Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.34 2003/05/05 00:44:55 tgl Exp $ -->
22

33
<chapter id="protocol">
44
<title>Frontend/Backend Protocol</title>
@@ -595,7 +595,11 @@
595595
<para>
596596
If successfully created, a named prepared-statement object lasts till
597597
the end of the current session, unless explicitly destroyed. An unnamed
598-
prepared statement lasts only until the next Parse message is issued.
598+
prepared statement lasts only until the next Parse statement specifying
599+
the unnamed statement as destination is issued. (Note that a simple
600+
Query message also destroys the unnamed statement.) Named prepared
601+
statements must be explicitly closed before they can be redefined by
602+
a Parse message, but this is not required for the unnamed statement.
599603
Named prepared statements can also be created and accessed at the SQL
600604
command level, using <command>PREPARE</> and <command>EXECUTE</>.
601605
</para>
@@ -611,10 +615,13 @@
611615
</para>
612616

613617
<para>
614-
If successfully created, a named portal object lasts till
615-
the end of the current transaction, unless explicitly destroyed. An
616-
unnamed portal is destroyed at the end of the transaction, or as soon
617-
as the next Parse or Bind message is executed.
618+
If successfully created, a named portal object lasts till the end of the
619+
current transaction, unless explicitly destroyed. An unnamed portal is
620+
destroyed at the end of the transaction, or as soon as the next Bind
621+
statement specifying the unnamed portal as destination is issued. (Note
622+
that a simple Query message also destroys the unnamed portal.) Named
623+
portals must be explicitly closed before they can be redefined by a Bind
624+
message, but this is not required for the unnamed portal.
618625
Named portals can also be created and accessed at the SQL
619626
command level, using <command>DECLARE CURSOR</> and <command>FETCH</>.
620627
</para>
@@ -691,37 +698,40 @@
691698
The Describe message (statement variant) specifies the name of an existing
692699
prepared statement (or an empty string for the unnamed prepared
693700
statement). The response is a ParameterDescription message describing the
694-
parameters needed by the statement (if any), followed by a RowDescription
695-
message describing the rows that will be returned when the statement is
696-
eventually executed (or NoData if there is no SELECT-type query in the
697-
prepared statement). ErrorResponse is issued if there is no such prepared
698-
statement. This message may be useful if the client library is
699-
uncertain about the parameters needed by a prepared statement.
701+
parameters needed by the statement. ErrorResponse is issued if there is
702+
no such prepared statement. This message may be useful if the client
703+
library is uncertain about the parameters needed by a prepared statement.
700704
</para>
701705

702706
<para>
703707
The Close message closes an existing prepared statement or portal
704-
and releases resources.
708+
and releases resources. It is not an error to issue Close against
709+
a nonexistent statement or portal name. The response is normally
710+
CloseComplete, but could be ErrorResponse if some difficulty is
711+
encountered while releasing resources. Note that closing a prepared
712+
statement implicitly closes any open portals that were constructed
713+
from that statement.
705714
</para>
706715

707716
<para>
708717
The Flush message does not cause any specific output to be generated,
709718
but forces the backend to deliver any data pending in its output
710719
buffers. A Flush must be sent after any extended-query command except
711720
Sync, if the frontend wishes to examine the results of that command before
712-
issuing more commands. Without Flush, returning data will be combined
713-
into the minimum possible number of packets to minimize network overhead.
721+
issuing more commands. Without Flush, messages returned by the backend
722+
will be combined into the minimum possible number of packets to minimize
723+
network overhead.
714724
</para>
715725

716726
<note>
717727
<para>
718728
The simple Query message is approximately equivalent to the series Parse,
719-
Bind, portal Describe, Execute, Sync, using the unnamed prepared statement
720-
and portal objects and no parameters. One difference is that it
721-
will accept multiple SQL statements in the query string, automatically
729+
Bind, portal Describe, Execute, Close, Sync, using the unnamed prepared
730+
statement and portal objects and no parameters. One difference is that
731+
it will accept multiple SQL statements in the query string, automatically
722732
performing the bind/describe/execute sequence for each one in succession.
723-
Another is that it will not return ParseComplete, BindComplete, or
724-
NoData messages.
733+
Another difference is that it will not return ParseComplete, BindComplete,
734+
CloseComplete, or NoData messages.
725735
</para>
726736
</note>
727737
</sect2>
@@ -1917,6 +1927,41 @@ Close (F)
19171927
</VarListEntry>
19181928

19191929

1930+
<VarListEntry>
1931+
<Term>
1932+
CloseComplete (B)
1933+
</Term>
1934+
<ListItem>
1935+
<Para>
1936+
1937+
<VariableList>
1938+
<VarListEntry>
1939+
<Term>
1940+
Byte1('3')
1941+
</Term>
1942+
<ListItem>
1943+
<Para>
1944+
Identifies the message as a Close-complete indicator.
1945+
</Para>
1946+
</ListItem>
1947+
</VarListEntry>
1948+
<VarListEntry>
1949+
<Term>
1950+
Int32(4)
1951+
</Term>
1952+
<ListItem>
1953+
<Para>
1954+
Length of message contents in bytes, including self.
1955+
</Para>
1956+
</ListItem>
1957+
</VarListEntry>
1958+
</VariableList>
1959+
1960+
</Para>
1961+
</ListItem>
1962+
</VarListEntry>
1963+
1964+
19201965
<VarListEntry>
19211966
<Term>
19221967
CommandComplete (B)
@@ -3875,6 +3920,15 @@ The ReadyForQuery ('<literal>Z</>') message includes a transaction status
38753920
indicator.
38763921
</para>
38773922

3923+
<para>
3924+
There is a new <quote>extended query</> sub-protocol, which adds the frontend
3925+
message types Parse, Bind, Execute, Describe, Close, Flush, and Sync, and the
3926+
backend message types ParseComplete, BindComplete, PortalSuspended,
3927+
ParameterDescription, NoData, and CloseComplete. Existing clients do not
3928+
have to concern themselves with this sub-protocol, but making use of it
3929+
may allow improvements in performance or functionality.
3930+
</para>
3931+
38783932
<para>
38793933
COPY data is now encapsulated into CopyData and CopyDone messages. There
38803934
is a well-defined way to recover from errors during COPY. The special

src/backend/access/common/printtup.c

+48-36
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.67 2003/04/26 20:22:58 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.68 2003/05/05 00:44:55 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -48,6 +48,7 @@ typedef struct
4848
typedef struct
4949
{
5050
DestReceiver pub; /* publicly-known function pointers */
51+
bool sendDescrip; /* send RowDescription at startup? */
5152
TupleDesc attrinfo; /* The attr info we are set up for */
5253
int nattrs;
5354
PrinttupAttrInfo *myinfo; /* Cached info about each attr */
@@ -58,14 +59,16 @@ typedef struct
5859
* ----------------
5960
*/
6061
DestReceiver *
61-
printtup_create_DR(bool isBinary)
62+
printtup_create_DR(bool isBinary, bool sendDescrip)
6263
{
6364
DR_printtup *self = (DR_printtup *) palloc(sizeof(DR_printtup));
6465

6566
self->pub.receiveTuple = isBinary ? printtup_internal : printtup;
6667
self->pub.setup = printtup_setup;
6768
self->pub.cleanup = printtup_cleanup;
6869

70+
self->sendDescrip = sendDescrip;
71+
6972
self->attrinfo = NULL;
7073
self->nattrs = 0;
7174
self->myinfo = NULL;
@@ -77,6 +80,8 @@ static void
7780
printtup_setup(DestReceiver *self, int operation,
7881
const char *portalName, TupleDesc typeinfo)
7982
{
83+
DR_printtup *myState = (DR_printtup *) self;
84+
8085
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
8186
{
8287
/*
@@ -91,41 +96,11 @@ printtup_setup(DestReceiver *self, int operation,
9196
}
9297

9398
/*
94-
* if this is a retrieve, then we send back the tuple descriptor of
95-
* the tuples.
99+
* If this is a retrieve, and we are supposed to emit row descriptions,
100+
* then we send back the tuple descriptor of the tuples.
96101
*/
97-
if (operation == CMD_SELECT)
98-
{
99-
Form_pg_attribute *attrs = typeinfo->attrs;
100-
int natts = typeinfo->natts;
101-
int proto = PG_PROTOCOL_MAJOR(FrontendProtocol);
102-
int i;
103-
StringInfoData buf;
104-
105-
pq_beginmessage(&buf, 'T'); /* tuple descriptor message type */
106-
pq_sendint(&buf, natts, 2); /* # of attrs in tuples */
107-
108-
for (i = 0; i < natts; ++i)
109-
{
110-
pq_sendstring(&buf, NameStr(attrs[i]->attname));
111-
/* column ID info appears in protocol 3.0 and up */
112-
if (proto >= 3)
113-
{
114-
/* XXX not yet implemented, send zeroes */
115-
pq_sendint(&buf, 0, 4);
116-
pq_sendint(&buf, 0, 2);
117-
}
118-
pq_sendint(&buf, (int) attrs[i]->atttypid,
119-
sizeof(attrs[i]->atttypid));
120-
pq_sendint(&buf, attrs[i]->attlen,
121-
sizeof(attrs[i]->attlen));
122-
/* typmod appears in protocol 2.0 and up */
123-
if (proto >= 2)
124-
pq_sendint(&buf, attrs[i]->atttypmod,
125-
sizeof(attrs[i]->atttypmod));
126-
}
127-
pq_endmessage(&buf);
128-
}
102+
if (operation == CMD_SELECT && myState->sendDescrip)
103+
SendRowDescriptionMessage(typeinfo);
129104

130105
/* ----------------
131106
* We could set up the derived attr info at this time, but we postpone it
@@ -139,6 +114,43 @@ printtup_setup(DestReceiver *self, int operation,
139114
*/
140115
}
141116

117+
/*
118+
* SendRowDescriptionMessage --- send a RowDescription message to the frontend
119+
*/
120+
void
121+
SendRowDescriptionMessage(TupleDesc typeinfo)
122+
{
123+
Form_pg_attribute *attrs = typeinfo->attrs;
124+
int natts = typeinfo->natts;
125+
int proto = PG_PROTOCOL_MAJOR(FrontendProtocol);
126+
int i;
127+
StringInfoData buf;
128+
129+
pq_beginmessage(&buf, 'T'); /* tuple descriptor message type */
130+
pq_sendint(&buf, natts, 2); /* # of attrs in tuples */
131+
132+
for (i = 0; i < natts; ++i)
133+
{
134+
pq_sendstring(&buf, NameStr(attrs[i]->attname));
135+
/* column ID info appears in protocol 3.0 and up */
136+
if (proto >= 3)
137+
{
138+
/* XXX not yet implemented, send zeroes */
139+
pq_sendint(&buf, 0, 4);
140+
pq_sendint(&buf, 0, 2);
141+
}
142+
pq_sendint(&buf, (int) attrs[i]->atttypid,
143+
sizeof(attrs[i]->atttypid));
144+
pq_sendint(&buf, attrs[i]->attlen,
145+
sizeof(attrs[i]->attlen));
146+
/* typmod appears in protocol 2.0 and up */
147+
if (proto >= 2)
148+
pq_sendint(&buf, attrs[i]->atttypmod,
149+
sizeof(attrs[i]->atttypmod));
150+
}
151+
pq_endmessage(&buf);
152+
}
153+
142154
static void
143155
printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
144156
{

src/backend/commands/portalcmds.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.13 2003/05/02 20:54:33 tgl Exp $
17+
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.14 2003/05/05 00:44:55 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -49,7 +49,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, CommandDest dest)
4949
* Disallow empty-string cursor name (conflicts with protocol-level
5050
* unnamed portal).
5151
*/
52-
if (strlen(stmt->portalname) == 0)
52+
if (!stmt->portalname || stmt->portalname[0] == '\0')
5353
elog(ERROR, "Invalid cursor name: must not be empty");
5454

5555
/*
@@ -148,6 +148,13 @@ PerformPortalFetch(FetchStmt *stmt,
148148
Portal portal;
149149
long nprocessed;
150150

151+
/*
152+
* Disallow empty-string cursor name (conflicts with protocol-level
153+
* unnamed portal).
154+
*/
155+
if (!stmt->portalname || stmt->portalname[0] == '\0')
156+
elog(ERROR, "Invalid cursor name: must not be empty");
157+
151158
/* get the portal from the portal name */
152159
portal = GetPortalByName(stmt->portalname);
153160
if (!PortalIsValid(portal))
@@ -164,7 +171,9 @@ PerformPortalFetch(FetchStmt *stmt,
164171
* Adjust dest if needed. MOVE wants dest = None.
165172
*
166173
* If fetching from a binary cursor and the requested destination is
167-
* Remote, change it to RemoteInternal.
174+
* Remote, change it to RemoteInternal. Note we do NOT change if the
175+
* destination is RemoteExecute --- so the Execute message's format
176+
* specification wins out over the cursor's type.
168177
*/
169178
if (stmt->ismove)
170179
dest = None;
@@ -189,10 +198,17 @@ PerformPortalFetch(FetchStmt *stmt,
189198
* Close a cursor.
190199
*/
191200
void
192-
PerformPortalClose(char *name)
201+
PerformPortalClose(const char *name)
193202
{
194203
Portal portal;
195204

205+
/*
206+
* Disallow empty-string cursor name (conflicts with protocol-level
207+
* unnamed portal).
208+
*/
209+
if (!name || name[0] == '\0')
210+
elog(ERROR, "Invalid cursor name: must not be empty");
211+
196212
/*
197213
* get the portal from the portal name
198214
*/

0 commit comments

Comments
 (0)