mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
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">
|
||||
<title>Frontend/Backend Protocol</title>
|
||||
@ -149,7 +149,8 @@
|
||||
<firstterm>bind</> step, which creates a portal given a prepared
|
||||
statement and values for any needed parameters; and an
|
||||
<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
|
||||
to complete the operation.
|
||||
</para>
|
||||
@ -456,7 +457,7 @@
|
||||
<ListItem>
|
||||
<Para>
|
||||
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
|
||||
will be followed by a DataRow or BinaryRow message (depending on
|
||||
whether a binary cursor was specified) for each row being returned
|
||||
@ -512,8 +513,8 @@
|
||||
</Para>
|
||||
|
||||
<Para>
|
||||
The response to a <command>SELECT</>, <command>FETCH</>, or
|
||||
<command>SHOW</> query
|
||||
The response to a <command>SELECT</> query (or other queries that
|
||||
return rowsets, such as <command>EXPLAIN</> or <command>SHOW</>)
|
||||
normally consists of RowDescription, zero or more
|
||||
DataRow or BinaryRow messages, and then CommandComplete.
|
||||
<command>COPY</> to or from the frontend invokes special protocol
|
||||
@ -632,8 +633,8 @@
|
||||
unnamed portal), the desired output format (text or binary), and
|
||||
a maximum result-row count (zero meaning <quote>fetch all rows</>).
|
||||
The output format and result-row count are only meaningful for portals
|
||||
containing SELECT commands; they are ignored for other types of commands.
|
||||
The possible
|
||||
containing commands that return rowsets; they are ignored for other types
|
||||
of commands. The possible
|
||||
responses to Execute are the same as those described above for queries
|
||||
issued via simple query protocol, except that Execute doesn't cause
|
||||
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
|
||||
RowDescription message describing the rows that will be returned by
|
||||
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
|
||||
situations the frontend will want to issue this message before issuing
|
||||
Execute, to obtain a description of the results it will get back.
|
||||
query that will return rows; or ErrorResponse if there is no such portal.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Describe message (statement variant) specifies the name of an existing
|
||||
prepared statement (or an empty string for the unnamed prepared
|
||||
statement). The response is a ParameterDescription message describing the
|
||||
parameters needed by the statement. ErrorResponse is issued if there is
|
||||
no such prepared statement. This message may be useful if the client
|
||||
library is uncertain about the parameters needed by a prepared statement.
|
||||
parameters needed by the statement (if any), followed by a RowDescription
|
||||
message describing the rows that will be returned when the statement is
|
||||
eventually executed (or NoData if the statement will not return rows).
|
||||
ErrorResponse is issued if there is no such prepared statement.
|
||||
</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>
|
||||
The Close message closes an existing prepared statement or portal
|
||||
and releases resources. It is not an error to issue Close against
|
||||
@ -2563,7 +2571,7 @@ Execute (F)
|
||||
<ListItem>
|
||||
<Para>
|
||||
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</>.
|
||||
</Para>
|
||||
</ListItem>
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* specified plan from storage.
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -1428,6 +1428,7 @@ static void
|
||||
exec_describe_statement_message(const char *stmt_name)
|
||||
{
|
||||
PreparedStatement *pstmt;
|
||||
TupleDesc tupdesc;
|
||||
List *l;
|
||||
StringInfoData buf;
|
||||
|
||||
@ -1445,6 +1446,9 @@ exec_describe_statement_message(const char *stmt_name)
|
||||
if (whereToSendOutput != Remote)
|
||||
return; /* can't actually do anything... */
|
||||
|
||||
/*
|
||||
* First describe the parameters...
|
||||
*/
|
||||
pq_beginmessage(&buf, 't'); /* parameter description message type */
|
||||
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_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)
|
||||
{
|
||||
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
|
||||
* $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);
|
||||
if (!PortalIsValid(portal))
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1077,7 +1072,7 @@ UtilityReturnsTuples(Node *parsetree)
|
||||
case PORTAL_UTIL_SELECT:
|
||||
return true;
|
||||
case PORTAL_MULTI_QUERY:
|
||||
/* can't figure it out, per note above */
|
||||
/* will not return tuples */
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@ -1124,25 +1119,13 @@ UtilityTupleDescriptor(Node *parsetree)
|
||||
{
|
||||
ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
|
||||
PreparedStatement *entry;
|
||||
Query *query;
|
||||
|
||||
if (stmt->into)
|
||||
return NULL;
|
||||
entry = FetchPreparedStatement(stmt->name, false);
|
||||
if (!entry)
|
||||
return NULL; /* not our business to raise error */
|
||||
switch (ChoosePortalStrategy(entry->query_list))
|
||||
{
|
||||
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;
|
||||
return FetchPreparedStatementResultDesc(entry);
|
||||
}
|
||||
|
||||
case T_ExplainStmt:
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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);
|
||||
extern void DropPreparedStatement(const char *stmt_name, bool showError);
|
||||
extern List *FetchPreparedStatementParams(const char *stmt_name);
|
||||
extern TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt);
|
||||
|
||||
#endif /* PREPARE_H */
|
||||
|
@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* 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. */
|
||||
|
||||
#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 */
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user