Add transaction status field to ReadyForQuery messages, and make room
authorTom Lane
Sat, 26 Apr 2003 20:23:00 +0000 (20:23 +0000)
committerTom Lane
Sat, 26 Apr 2003 20:23:00 +0000 (20:23 +0000)
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.)

doc/src/sgml/protocol.sgml
src/backend/access/common/printtup.c
src/backend/access/transam/xact.c
src/backend/tcop/dest.c
src/include/access/xact.h
src/include/libpq/pqcomm.h
src/interfaces/libpq/fe-exec.c
src/interfaces/libpq/libpq-int.h

index 70c255f00ce5930bcc3917e3a27b78d7840c4afc..635fc7715b4f8cf5ef18c4721d0b7da12e18c016 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  Frontend/Backend Protocol
@@ -3870,6 +3870,11 @@ individual fields will typically not end with a newline, whereas the single
 string sent in the older protocol always did.
 
 
+
+The ReadyForQuery ('Z') message includes a transaction status
+indicator.
+
+
 
 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.
 
 
@@ -3888,6 +3893,11 @@ Subsequently, a ParameterStatus message is sent whenever the active value
 changes for any of these parameters.
 
 
+
+The RowDescription ('T') message carries new table OID and column
+number fields for each column of the described row.
+
+
 
 The CursorResponse ('P') message is no longer generated by
 the backend.
index c88dedd93fd62697ae96e68b8bee444986155136..160b703223f5d973f7d9eb6bfc6f93a44cac869b 100644 (file)
@@ -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));
        }
index 598e3c880e5ed0e0bb345d4a153dcf34ba8d52b1..a15985d3bd787f808142ef00283c5b39f4ccf511 100644 (file)
@@ -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 */
 }
 
 
index 5ccaa60995c5ae39a4693c4a8ae877eab5ff13c1..41906a348a461fdd3b590f7a8a63187d7bba553f 100644 (file)
@@ -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();
index b3938c869e1f759a5df90b3ce6f7e16f37593935..5525ce74457eabd575a2ec6be2072f4a594e9343 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 
 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);
index 6a871c7c6f61ec427a0f327edc66b5f66586d8c1..d5374a68fe6d53edc0f5415194760165765d1160 100644 (file)
@@ -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 */
 
index 53c4e2886225e7b6a1f3381ab9d77bec5c31fb0f..db513d64ef5df47c325c4be69d326a04fbc67b7c 100644 (file)
@@ -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);
index 12670f3a0a4e694e22e3ce24de7ac87f47ea865d..a5e6bceef4216315b922b0f443b1faa1f0082100 100644 (file)
@@ -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