mirror of
https://github.com/postgres/postgres.git
synced 2025-06-04 00:02:37 -04:00
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.)
This commit is contained in:
parent
2b1e36c7c0
commit
4db9689d1a
@ -1,4 +1,4 @@
|
||||
<!-- $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
|
||||
|
Loading…
x
Reference in New Issue
Block a user