Add display of eventual result RowDescription (if any) to the output
of Describe on a prepared statement. This was in the original 3.0 protocol proposal, but I took it out for reasons that seemed good at the time. Put it back per yesterday's pghackers discussion.
This commit is contained in:
parent
8f6a6b7e9a
commit
755d191700
@ -1,4 +1,4 @@
|
|||||||
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.34 2003/05/05 00:44:55 tgl Exp $ -->
|
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.35 2003/05/06 21:51:41 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="protocol">
|
<chapter id="protocol">
|
||||||
<title>Frontend/Backend Protocol</title>
|
<title>Frontend/Backend Protocol</title>
|
||||||
@ -149,7 +149,8 @@
|
|||||||
<firstterm>bind</> step, which creates a portal given a prepared
|
<firstterm>bind</> step, which creates a portal given a prepared
|
||||||
statement and values for any needed parameters; and an
|
statement and values for any needed parameters; and an
|
||||||
<firstterm>execute</> step that runs a portal's query. In the case of
|
<firstterm>execute</> step that runs a portal's query. In the case of
|
||||||
a <command>SELECT</> query, the execute step can be told to fetch only
|
a query that returns rows (<command>SELECT</>, <command>SHOW</>, etc),
|
||||||
|
the execute step can be told to fetch only
|
||||||
a limited number of rows, so that multiple execute steps may be needed
|
a limited number of rows, so that multiple execute steps may be needed
|
||||||
to complete the operation.
|
to complete the operation.
|
||||||
</para>
|
</para>
|
||||||
@ -456,7 +457,7 @@
|
|||||||
<ListItem>
|
<ListItem>
|
||||||
<Para>
|
<Para>
|
||||||
Indicates that rows are about to be returned in response to
|
Indicates that rows are about to be returned in response to
|
||||||
a <command>SELECT</command> or <command>FETCH</command> query.
|
a <command>SELECT</command>, <command>FETCH</command>, etc query.
|
||||||
The message contents describe the layout of the rows. This
|
The message contents describe the layout of the rows. This
|
||||||
will be followed by a DataRow or BinaryRow message (depending on
|
will be followed by a DataRow or BinaryRow message (depending on
|
||||||
whether a binary cursor was specified) for each row being returned
|
whether a binary cursor was specified) for each row being returned
|
||||||
@ -512,8 +513,8 @@
|
|||||||
</Para>
|
</Para>
|
||||||
|
|
||||||
<Para>
|
<Para>
|
||||||
The response to a <command>SELECT</>, <command>FETCH</>, or
|
The response to a <command>SELECT</> query (or other queries that
|
||||||
<command>SHOW</> query
|
return rowsets, such as <command>EXPLAIN</> or <command>SHOW</>)
|
||||||
normally consists of RowDescription, zero or more
|
normally consists of RowDescription, zero or more
|
||||||
DataRow or BinaryRow messages, and then CommandComplete.
|
DataRow or BinaryRow messages, and then CommandComplete.
|
||||||
<command>COPY</> to or from the frontend invokes special protocol
|
<command>COPY</> to or from the frontend invokes special protocol
|
||||||
@ -632,8 +633,8 @@
|
|||||||
unnamed portal), the desired output format (text or binary), and
|
unnamed portal), the desired output format (text or binary), and
|
||||||
a maximum result-row count (zero meaning <quote>fetch all rows</>).
|
a maximum result-row count (zero meaning <quote>fetch all rows</>).
|
||||||
The output format and result-row count are only meaningful for portals
|
The output format and result-row count are only meaningful for portals
|
||||||
containing SELECT commands; they are ignored for other types of commands.
|
containing commands that return rowsets; they are ignored for other types
|
||||||
The possible
|
of commands. The possible
|
||||||
responses to Execute are the same as those described above for queries
|
responses to Execute are the same as those described above for queries
|
||||||
issued via simple query protocol, except that Execute doesn't cause
|
issued via simple query protocol, except that Execute doesn't cause
|
||||||
ReadyForQuery to be issued. Also, the choice between text and binary
|
ReadyForQuery to be issued. Also, the choice between text and binary
|
||||||
@ -689,20 +690,27 @@
|
|||||||
portal (or an empty string for the unnamed portal). The response is a
|
portal (or an empty string for the unnamed portal). The response is a
|
||||||
RowDescription message describing the rows that will be returned by
|
RowDescription message describing the rows that will be returned by
|
||||||
executing the portal; or a NoData message if the portal does not contain a
|
executing the portal; or a NoData message if the portal does not contain a
|
||||||
SELECT-type query; or ErrorResponse if there is no such portal. In most
|
query that will return rows; or ErrorResponse if there is no such portal.
|
||||||
situations the frontend will want to issue this message before issuing
|
|
||||||
Execute, to obtain a description of the results it will get back.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The Describe message (statement variant) specifies the name of an existing
|
The Describe message (statement variant) specifies the name of an existing
|
||||||
prepared statement (or an empty string for the unnamed prepared
|
prepared statement (or an empty string for the unnamed prepared
|
||||||
statement). The response is a ParameterDescription message describing the
|
statement). The response is a ParameterDescription message describing the
|
||||||
parameters needed by the statement. ErrorResponse is issued if there is
|
parameters needed by the statement (if any), followed by a RowDescription
|
||||||
no such prepared statement. This message may be useful if the client
|
message describing the rows that will be returned when the statement is
|
||||||
library is uncertain about the parameters needed by a prepared statement.
|
eventually executed (or NoData if the statement will not return rows).
|
||||||
|
ErrorResponse is issued if there is no such prepared statement.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
In most scenarios the frontend should issue one or the other variant
|
||||||
|
of Describe before issuing Execute, to ensure that it knows how to
|
||||||
|
interpret the results it will get back.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The Close message closes an existing prepared statement or portal
|
The Close message closes an existing prepared statement or portal
|
||||||
and releases resources. It is not an error to issue Close against
|
and releases resources. It is not an error to issue Close against
|
||||||
@ -2563,7 +2571,7 @@ Execute (F)
|
|||||||
<ListItem>
|
<ListItem>
|
||||||
<Para>
|
<Para>
|
||||||
Maximum number of rows to return, if portal contains
|
Maximum number of rows to return, if portal contains
|
||||||
a SELECT or FETCH query (ignored otherwise). Zero
|
a query that returns rows (ignored otherwise). Zero
|
||||||
denotes <quote>no limit</>.
|
denotes <quote>no limit</>.
|
||||||
</Para>
|
</Para>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.16 2003/05/06 20:26:26 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.17 2003/05/06 21:51:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -393,6 +393,34 @@ FetchPreparedStatementParams(const char *stmt_name)
|
|||||||
return entry->argtype_list;
|
return entry->argtype_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a prepared statement, determine the result tupledesc it will
|
||||||
|
* produce. Returns NULL if the execution will not return tuples.
|
||||||
|
*
|
||||||
|
* Note: the result is created or copied into current memory context.
|
||||||
|
*/
|
||||||
|
TupleDesc
|
||||||
|
FetchPreparedStatementResultDesc(PreparedStatement *stmt)
|
||||||
|
{
|
||||||
|
Query *query;
|
||||||
|
|
||||||
|
switch (ChoosePortalStrategy(stmt->query_list))
|
||||||
|
{
|
||||||
|
case PORTAL_ONE_SELECT:
|
||||||
|
query = (Query *) lfirst(stmt->query_list);
|
||||||
|
return ExecCleanTypeFromTL(query->targetList, false);
|
||||||
|
|
||||||
|
case PORTAL_UTIL_SELECT:
|
||||||
|
query = (Query *) lfirst(stmt->query_list);
|
||||||
|
return UtilityTupleDescriptor(query->utilityStmt);
|
||||||
|
|
||||||
|
case PORTAL_MULTI_QUERY:
|
||||||
|
/* will not return tuples */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implements the 'DEALLOCATE' utility statement: deletes the
|
* Implements the 'DEALLOCATE' utility statement: deletes the
|
||||||
* specified plan from storage.
|
* specified plan from storage.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.336 2003/05/06 20:26:27 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.337 2003/05/06 21:51:41 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -1428,6 +1428,7 @@ static void
|
|||||||
exec_describe_statement_message(const char *stmt_name)
|
exec_describe_statement_message(const char *stmt_name)
|
||||||
{
|
{
|
||||||
PreparedStatement *pstmt;
|
PreparedStatement *pstmt;
|
||||||
|
TupleDesc tupdesc;
|
||||||
List *l;
|
List *l;
|
||||||
StringInfoData buf;
|
StringInfoData buf;
|
||||||
|
|
||||||
@ -1445,6 +1446,9 @@ exec_describe_statement_message(const char *stmt_name)
|
|||||||
if (whereToSendOutput != Remote)
|
if (whereToSendOutput != Remote)
|
||||||
return; /* can't actually do anything... */
|
return; /* can't actually do anything... */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First describe the parameters...
|
||||||
|
*/
|
||||||
pq_beginmessage(&buf, 't'); /* parameter description message type */
|
pq_beginmessage(&buf, 't'); /* parameter description message type */
|
||||||
pq_sendint(&buf, length(pstmt->argtype_list), 4);
|
pq_sendint(&buf, length(pstmt->argtype_list), 4);
|
||||||
|
|
||||||
@ -1455,6 +1459,24 @@ exec_describe_statement_message(const char *stmt_name)
|
|||||||
pq_sendint(&buf, (int) ptype, 4);
|
pq_sendint(&buf, (int) ptype, 4);
|
||||||
}
|
}
|
||||||
pq_endmessage(&buf);
|
pq_endmessage(&buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Next send RowDescription or NoData to describe the result...
|
||||||
|
*/
|
||||||
|
tupdesc = FetchPreparedStatementResultDesc(pstmt);
|
||||||
|
if (tupdesc)
|
||||||
|
{
|
||||||
|
List *targetlist;
|
||||||
|
|
||||||
|
if (ChoosePortalStrategy(pstmt->query_list) == PORTAL_ONE_SELECT)
|
||||||
|
targetlist = ((Query *) lfirst(pstmt->query_list))->targetList;
|
||||||
|
else
|
||||||
|
targetlist = NIL;
|
||||||
|
SendRowDescriptionMessage(tupdesc, targetlist);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pq_putemptymessage('n'); /* NoData */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2359,7 +2381,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
|||||||
if (!IsUnderPostmaster)
|
if (!IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
puts("\nPOSTGRES backend interactive interface ");
|
puts("\nPOSTGRES backend interactive interface ");
|
||||||
puts("$Revision: 1.336 $ $Date: 2003/05/06 20:26:27 $\n");
|
puts("$Revision: 1.337 $ $Date: 2003/05/06 21:51:41 $\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.199 2003/05/06 20:26:27 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.200 2003/05/06 21:51:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1052,11 +1052,6 @@ UtilityReturnsTuples(Node *parsetree)
|
|||||||
portal = GetPortalByName(stmt->portalname);
|
portal = GetPortalByName(stmt->portalname);
|
||||||
if (!PortalIsValid(portal))
|
if (!PortalIsValid(portal))
|
||||||
return false; /* not our business to raise error */
|
return false; /* not our business to raise error */
|
||||||
/*
|
|
||||||
* Note: if portal contains multiple statements then it's
|
|
||||||
* possible some of them will return tuples, but we don't
|
|
||||||
* handle that case here.
|
|
||||||
*/
|
|
||||||
return portal->tupDesc ? true : false;
|
return portal->tupDesc ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,7 +1072,7 @@ UtilityReturnsTuples(Node *parsetree)
|
|||||||
case PORTAL_UTIL_SELECT:
|
case PORTAL_UTIL_SELECT:
|
||||||
return true;
|
return true;
|
||||||
case PORTAL_MULTI_QUERY:
|
case PORTAL_MULTI_QUERY:
|
||||||
/* can't figure it out, per note above */
|
/* will not return tuples */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1124,25 +1119,13 @@ UtilityTupleDescriptor(Node *parsetree)
|
|||||||
{
|
{
|
||||||
ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
|
ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
|
||||||
PreparedStatement *entry;
|
PreparedStatement *entry;
|
||||||
Query *query;
|
|
||||||
|
|
||||||
if (stmt->into)
|
if (stmt->into)
|
||||||
return NULL;
|
return NULL;
|
||||||
entry = FetchPreparedStatement(stmt->name, false);
|
entry = FetchPreparedStatement(stmt->name, false);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return NULL; /* not our business to raise error */
|
return NULL; /* not our business to raise error */
|
||||||
switch (ChoosePortalStrategy(entry->query_list))
|
return FetchPreparedStatementResultDesc(entry);
|
||||||
{
|
|
||||||
case PORTAL_ONE_SELECT:
|
|
||||||
query = (Query *) lfirst(entry->query_list);
|
|
||||||
return ExecCleanTypeFromTL(query->targetList, false);
|
|
||||||
case PORTAL_UTIL_SELECT:
|
|
||||||
query = (Query *) lfirst(entry->query_list);
|
|
||||||
return UtilityTupleDescriptor(query->utilityStmt);
|
|
||||||
case PORTAL_MULTI_QUERY:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case T_ExplainStmt:
|
case T_ExplainStmt:
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Id: prepare.h,v 1.5 2003/05/06 20:26:27 tgl Exp $
|
* $Id: prepare.h,v 1.6 2003/05/06 21:51:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -57,5 +57,6 @@ extern PreparedStatement *FetchPreparedStatement(const char *stmt_name,
|
|||||||
bool throwError);
|
bool throwError);
|
||||||
extern void DropPreparedStatement(const char *stmt_name, bool showError);
|
extern void DropPreparedStatement(const char *stmt_name, bool showError);
|
||||||
extern List *FetchPreparedStatementParams(const char *stmt_name);
|
extern List *FetchPreparedStatementParams(const char *stmt_name);
|
||||||
|
extern TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt);
|
||||||
|
|
||||||
#endif /* PREPARE_H */
|
#endif /* PREPARE_H */
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pqcomm.h,v 1.82 2003/05/05 00:44:56 tgl Exp $
|
* $Id: pqcomm.h,v 1.83 2003/05/06 21:51:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -106,7 +106,7 @@ typedef union SockAddr
|
|||||||
/* The earliest and latest frontend/backend protocol version supported. */
|
/* The earliest and latest frontend/backend protocol version supported. */
|
||||||
|
|
||||||
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(1,0)
|
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(1,0)
|
||||||
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,106) /* XXX temporary value */
|
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,107) /* XXX temporary value */
|
||||||
|
|
||||||
typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
|
typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: libpq-int.h,v 1.67 2003/05/05 00:44:56 tgl Exp $
|
* $Id: libpq-int.h,v 1.68 2003/05/06 21:51:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -56,7 +56,7 @@ typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast
|
|||||||
* pqcomm.h describe what the backend knows, not what libpq knows.
|
* pqcomm.h describe what the backend knows, not what libpq knows.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PG_PROTOCOL_LIBPQ PG_PROTOCOL(3,106) /* XXX temporary value */
|
#define PG_PROTOCOL_LIBPQ PG_PROTOCOL(3,107) /* XXX temporary value */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* POSTGRES backend dependent Constants.
|
* POSTGRES backend dependent Constants.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user