Commit 4db9689d authored by Tom Lane's avatar Tom Lane

Add transaction status field to ReadyForQuery messages, and make room

for tableID/columnID in RowDescription.  (The latter isn't really
implemented yet though --- the backend always sends zeroes, and libpq
just throws away the data.)
parent 2b1e36c7
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.31 2003/04/25 19:45:08 tgl Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.32 2003/04/26 20:22:57 tgl Exp $ -->
<chapter id="protocol">
<title>Frontend/Backend Protocol</title>
......@@ -3870,6 +3870,11 @@ individual fields will typically not end with a newline, whereas the single
string sent in the older protocol always did.
</para>
<para>
The ReadyForQuery ('<literal>Z</>') message includes a transaction status
indicator.
</para>
<para>
COPY data is now encapsulated into CopyData and CopyDone messages. There
is a well-defined way to recover from errors during COPY. The special
......@@ -3877,7 +3882,7 @@ is a well-defined way to recover from errors during COPY. The special
during COPY OUT.
(It is still recognized as a terminator during COPY IN, but its use is
deprecated and will eventually be removed.) Binary COPY is supported.
The CopyInResponse and CopyOutResponse messages carry a field indicating
The CopyInResponse and CopyOutResponse messages include a field indicating
whether the COPY operation is text or binary.
</para>
......@@ -3888,6 +3893,11 @@ Subsequently, a ParameterStatus message is sent whenever the active value
changes for any of these parameters.
</para>
<para>
The RowDescription ('<literal>T</>') message carries new table OID and column
number fields for each column of the described row.
</para>
<para>
The CursorResponse ('<literal>P</>') message is no longer generated by
the backend.
......
......@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.66 2003/04/22 00:08:06 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.67 2003/04/26 20:22:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -98,6 +98,7 @@ printtup_setup(DestReceiver *self, int operation,
{
Form_pg_attribute *attrs = typeinfo->attrs;
int natts = typeinfo->natts;
int proto = PG_PROTOCOL_MAJOR(FrontendProtocol);
int i;
StringInfoData buf;
......@@ -107,11 +108,19 @@ printtup_setup(DestReceiver *self, int operation,
for (i = 0; i < natts; ++i)
{
pq_sendstring(&buf, NameStr(attrs[i]->attname));
/* column ID info appears in protocol 3.0 and up */
if (proto >= 3)
{
/* XXX not yet implemented, send zeroes */
pq_sendint(&buf, 0, 4);
pq_sendint(&buf, 0, 2);
}
pq_sendint(&buf, (int) attrs[i]->atttypid,
sizeof(attrs[i]->atttypid));
pq_sendint(&buf, attrs[i]->attlen,
sizeof(attrs[i]->attlen));
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
/* typmod appears in protocol 2.0 and up */
if (proto >= 2)
pq_sendint(&buf, attrs[i]->atttypmod,
sizeof(attrs[i]->atttypmod));
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.145 2003/03/27 16:51:27 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.146 2003/04/26 20:22:59 tgl Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
......@@ -1705,17 +1705,44 @@ AbortOutOfAnyTransaction(void)
s->blockState = TBLOCK_DEFAULT;
}
/*
* IsTransactionBlock --- are we within a transaction block?
*/
bool
IsTransactionBlock(void)
{
TransactionState s = CurrentTransactionState;
if (s->blockState == TBLOCK_INPROGRESS
|| s->blockState == TBLOCK_ABORT
|| s->blockState == TBLOCK_ENDABORT)
return true;
if (s->blockState == TBLOCK_DEFAULT)
return false;
return false;
return true;
}
/*
* TransactionBlockStatusCode - return status code to send in ReadyForQuery
*/
char
TransactionBlockStatusCode(void)
{
TransactionState s = CurrentTransactionState;
switch (s->blockState)
{
case TBLOCK_DEFAULT:
return 'I'; /* idle --- not in transaction */
case TBLOCK_BEGIN:
case TBLOCK_INPROGRESS:
case TBLOCK_END:
return 'T'; /* in transaction */
case TBLOCK_ABORT:
case TBLOCK_ENDABORT:
return 'E'; /* in failed transaction */
}
/* should never get here */
elog(ERROR, "bogus transaction block state");
return 0; /* keep compiler quiet */
}
......
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.53 2003/04/22 00:08:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.54 2003/04/26 20:22:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -29,6 +29,7 @@
#include "postgres.h"
#include "access/printtup.h"
#include "access/xact.h"
#include "executor/tstoreReceiver.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
......@@ -177,6 +178,7 @@ NullCommand(CommandDest dest)
*
* The ReadyForQuery message is sent in protocol versions 2.0 and up
* so that the FE can tell when we are done processing a query string.
* In versions 3.0 and up, it also carries a transaction state indicator.
*
* Note that by flushing the stdio buffer here, we can avoid doing it
* most other places and thus reduce the number of separate packets sent.
......@@ -189,7 +191,15 @@ ReadyForQuery(CommandDest dest)
{
case RemoteInternal:
case Remote:
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
{
StringInfoData buf;
pq_beginmessage(&buf, 'Z');
pq_sendbyte(&buf, TransactionBlockStatusCode());
pq_endmessage(&buf);
}
else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
pq_putemptymessage('Z');
/* Flush output at end of cycle in any case. */
pq_flush();
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: xact.h,v 1.49 2003/01/10 22:03:30 petere Exp $
* $Id: xact.h,v 1.50 2003/04/26 20:22:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -29,9 +29,35 @@
extern int DefaultXactIsoLevel;
extern int XactIsoLevel;
/* Xact read-only state */
extern bool DefaultXactReadOnly;
extern bool XactReadOnly;
/*
* transaction states - transaction state from server perspective
*/
typedef enum TransState
{
TRANS_DEFAULT,
TRANS_START,
TRANS_INPROGRESS,
TRANS_COMMIT,
TRANS_ABORT
} TransState;
/*
* transaction block states - transaction state of client queries
*/
typedef enum TBlockState
{
TBLOCK_DEFAULT,
TBLOCK_BEGIN,
TBLOCK_INPROGRESS,
TBLOCK_END,
TBLOCK_ABORT,
TBLOCK_ENDABORT
} TBlockState;
/* ----------------
* transaction state structure
......@@ -43,33 +69,17 @@ typedef struct TransactionStateData
CommandId commandId;
AbsoluteTime startTime;
int startTimeUsec;
int state;
int blockState;
TransState state;
TBlockState blockState;
} TransactionStateData;
typedef TransactionStateData *TransactionState;
/*
* transaction states - transaction state from server perspective
*
* Syntax error could cause transaction to abort, but client code thinks
* it is still in a transaction, so we have to wait for COMMIT/ROLLBACK.
*/
#define TRANS_DEFAULT 0
#define TRANS_START 1
#define TRANS_INPROGRESS 2
#define TRANS_COMMIT 3
#define TRANS_ABORT 4
/*
* transaction block states - transaction state of client queries
/* ----------------
* transaction-related XLOG entries
* ----------------
*/
#define TBLOCK_DEFAULT 0
#define TBLOCK_BEGIN 1
#define TBLOCK_INPROGRESS 2
#define TBLOCK_END 3
#define TBLOCK_ABORT 4
#define TBLOCK_ENDABORT 5
/*
* XLOG allows to store some information in high 4 bits of log
......@@ -115,6 +125,7 @@ extern void AbortCurrentTransaction(void);
extern void BeginTransactionBlock(void);
extern void EndTransactionBlock(void);
extern bool IsTransactionBlock(void);
extern char TransactionBlockStatusCode(void);
extern void UserAbortTransactionBlock(void);
extern void AbortOutOfAnyTransaction(void);
extern void PreventTransactionChain(void *stmtNode, const char *stmtType);
......
......@@ -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.80 2003/04/25 19:45:09 tgl Exp $
* $Id: pqcomm.h,v 1.81 2003/04/26 20:22:59 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,104) /* XXX temporary value */
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,105) /* XXX temporary value */
typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.133 2003/04/25 19:45:09 tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.134 2003/04/26 20:22:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1027,6 +1027,8 @@ parseInput(PGconn *conn)
conn->asyncStatus = PGASYNC_READY;
break;
case 'Z': /* backend is ready for new query */
if (pqGetc(&conn->xact_status, conn))
return;
conn->asyncStatus = PGASYNC_IDLE;
break;
case 'I': /* empty query */
......@@ -1222,11 +1224,15 @@ getRowDescriptions(PGconn *conn)
/* get type info */
for (i = 0; i < nfields; i++)
{
int tableid;
int columnid;
int typid;
int typlen;
int atttypmod;
if (pqGets(&conn->workBuffer, conn) ||
pqGetInt(&tableid, 4, conn) ||
pqGetInt(&columnid, 2, conn) ||
pqGetInt(&typid, 4, conn) ||
pqGetInt(&typlen, 2, conn) ||
pqGetInt(&atttypmod, 4, conn))
......@@ -1237,8 +1243,9 @@ getRowDescriptions(PGconn *conn)
/*
* Since pqGetInt treats 2-byte integers as unsigned, we need to
* coerce the result to signed form.
* coerce these results to signed form.
*/
columnid = (int) ((int16) columnid);
typlen = (int) ((int16) typlen);
result->attDescs[i].name = pqResultStrdup(result,
......@@ -1246,6 +1253,7 @@ getRowDescriptions(PGconn *conn)
result->attDescs[i].typid = typid;
result->attDescs[i].typlen = typlen;
result->attDescs[i].atttypmod = atttypmod;
/* XXX todo: save tableid/columnid too */
}
/* Success! */
......@@ -2289,9 +2297,10 @@ PQfn(PGconn *conn,
continue;
break;
case 'Z': /* backend is ready for new query */
if (pqGetc(&conn->xact_status, conn))
continue;
/* consume the message and exit */
conn->inStart += 5 + msgLength;
/* XXX expect additional fields here */
/* if we saved a result object (probably an error), use it */
if (conn->result)
return prepareAsyncResult(conn);
......
......@@ -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.65 2003/04/25 19:45:10 tgl Exp $
* $Id: libpq-int.h,v 1.66 2003/04/26 20:23:00 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,104) /* XXX temporary value */
#define PG_PROTOCOL_LIBPQ PG_PROTOCOL(3,105) /* XXX temporary value */
/*
* POSTGRES backend dependent Constants.
......@@ -241,6 +241,7 @@ struct pg_conn
/* Status indicators */
ConnStatusType status;
PGAsyncStatusType asyncStatus;
char xact_status; /* status flag from latest ReadyForQuery */
char copy_is_binary; /* 1 = copy binary, 0 = copy text */
int copy_already_done; /* # bytes already returned in COPY OUT */
int nonblocking; /* whether this connection is using a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment