Hackers,

I tried to implement the reporting of the current transaction level to
the client using an ad-hoc ParameterStatus message.  Seems it works.
To see it working I added a %d escape to psql prompt processing:

alvherre=# \set PROMPT1 '[EMAIL PROTECTED]/%R[%d]%x '
[EMAIL PROTECTED] begin;
BEGIN
[EMAIL PROTECTED] savepoint foo;
SAVEPOINT
[EMAIL PROTECTED] savepoint bar;
SAVEPOINT
[EMAIL PROTECTED] release foo;
RELEASE
[EMAIL PROTECTED] savepoint another;
SAVEPOINT
[EMAIL PROTECTED] commit;
COMMIT
[EMAIL PROTECTED] 


(The nesting level, obviously, is the number between [ ]; the * is the
"in transaction" mark, which existed previously.  Yes, it works if it's
> 9.)

Patch attached (surprinsingly small), though it only applies with the
savepoint patch applied(*).  If any driver writer wants to play, however,
it's easy to see what's going on -- a ParameterStatus message will be
received from the backend whenever the nesting level changes.

I added a function PQnestingLevel() to libpq, and a corresponding field
in pg_conn.  We have to decide if we like the name, and whether we want
to have it at all.

(This is different from the previous idea in that the nesting level is
not a GUC variable -- the message is sent directly from xact.c.  If this
is a bad idea, just moving the SendTransactionNestingLevel() function
can be moved somewhere else, though I couldn't figure out where.)



(*)  Even then, this is hand-edited output of interdiff, so maybe it
doesn't apply at all ... if this is the case I'll submit a better patch
tomorrow.

-- 
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"No hay hombre que no aspire a la plenitud, es decir,
la suma de experiencias de que un hombre es capaz"
diff -u src/backend/access/transam/xact.c src/backend/access/transam/xact.c
--- src/backend/access/transam/xact.c   16 Jul 2004 05:40:09 -0000
+++ src/backend/access/transam/xact.c   16 Jul 2004 07:04:35 -0000
@@ -159,6 +159,8 @@
 #include "commands/user.h"
 #include "executor/spi.h"
 #include "libpq/be-fsstubs.h"
+#include "lib/stringinfo.h"
+#include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "storage/fd.h"
 #include "storage/proc.h"
@@ -341,6 +343,7 @@
 static void ShowTransactionStateRec(TransactionState state);
 static const char *BlockStateAsString(TBlockState blockState);
 static const char *TransStateAsString(TransState state);
+static void SendTransactionNestingLevel(void);
 
 /* ----------------------------------------------------------------
  *     transaction state accessors
@@ -1360,6 +1369,8 @@
         */
        s->state = TRANS_INPROGRESS;
 
+       SendTransactionNestingLevel();
+
        ShowTransactionState("StartTransaction");
 }
 
@@ -1486,6 +1508,8 @@
         */
        s->state = TRANS_DEFAULT;
 
+       SendTransactionNestingLevel();
+
        RESUME_INTERRUPTS();
 }
 
@@ -1627,6 +1651,8 @@
        s->nestingLevel = 0;
        s->childXids = NIL;
 
+       SendTransactionNestingLevel();
+
        /*
         * done with abort processing, set current transaction state back to
         * default
@@ -2741,6 +2767,8 @@
                        s->blockState != TBLOCK_SUBENDABORT_ALL)
                AbortSubTransaction();
        s->blockState = TBLOCK_SUBABORT;
+
+       SendTransactionNestingLevel();
 }
 
 /*
@@ -2762,6 +2790,8 @@
                PopTransaction();
                s = CurrentTransactionState;                            /* changed by 
pop */
        }
+
+       SendTransactionNestingLevel();
 }
 
 /*
@@ -2893,15 +2930,17 @@
        /* Initialize the various transaction subsystems */
        AtSubStart_Memory();
        AtSubStart_Inval();
        AtSubStart_RelationCache();
        AtSubStart_CatCache();
        AtSubStart_Buffers();
        AtSubStart_smgr();
        AtSubStart_Notify();
        DeferredTriggerBeginSubXact();
 
        s->state = TRANS_INPROGRESS;
 
+       SendTransactionNestingLevel();
+
        ShowTransactionState("StartSubTransaction");
 }
 
@@ -2942,11 +2981,13 @@
        AtEOSubXact_on_commit_actions(true, s->transactionIdData,
                                                                  
s->parent->transactionIdData);
 
        AtEOSubXact_CatCache(true);
        AtEOSubXact_RelationCache(true);
        AtEOSubXact_Buffers(true);
        AtSubCommit_Memory();
 
+       SendTransactionNestingLevel();
+
        s->state = TRANS_DEFAULT;
 }
 
@@ -3045,6 +3087,8 @@
        AtSubCleanup_Portals();
        AtSubCleanup_Memory();
 
+       SendTransactionNestingLevel();
+
        s->state = TRANS_DEFAULT;
 }
 
@@ -3160,6 +3204,22 @@
        pfree(s);
 }
 
+static void
+SendTransactionNestingLevel(void)
+{
+       char    *val = (char *)palloc(12);
+       StringInfoData msgbuf;
+
+       snprintf(val, 12, "%d", CurrentTransactionState->nestingLevel);
+
+       pq_beginmessage(&msgbuf, 'S');
+       pq_sendstring(&msgbuf, "nesting_level");
+       pq_sendstring(&msgbuf, val);
+       pq_endmessage(&msgbuf);
+
+       pfree(val);
+}
+
 /*
  * ShowTransactionState
  *             Debug support
--- src/bin/psql/prompt.c       24 Feb 2004 21:45:18 -0000      1.35
+++ src/bin/psql/prompt.c       16 Jul 2004 06:39:33 -0000
@@ -46,6 +46,7 @@
  *             in prompt2 -, *, ', or ";
  *             in prompt3 nothing
  * %x - transaction status: empty, *, !, ? (unknown or no connection)
+ * %d - transaction nesting level
  * %? - the error code of the last query (not yet implemented)
  * %% - a percent sign
  *
@@ -237,6 +238,13 @@
                                                }
                                        break;
 
+                               case 'd':
+                                       if (!pset.db)
+                                               buf[0] = '?';
+                                       else
+                                               snprintf(buf, MAX_PROMPT_SIZE, "%d", 
PQnestingLevel(pset.db));
+                                       break;
+
                                case '?':
                                        /* not here yet */
                                        break;
--- src/interfaces/libpq/fe-connect.c   12 Jul 2004 14:23:28 -0000      1.278
+++ src/interfaces/libpq/fe-connect.c   16 Jul 2004 06:35:31 -0000
@@ -2847,6 +2847,14 @@
        return conn->xactStatus;
 }
 
+int
+PQnestingLevel(const PGconn *conn)
+{
+       if (!conn || conn->status != CONNECTION_OK)
+               return -1;
+       return conn->nestingLevel;
+}
+
 const char *
 PQparameterStatus(const PGconn *conn, const char *paramName)
 {
only in patch2:
unchanged:
--- src/interfaces/libpq/fe-exec.c      7 May 2004 00:24:59 -0000       1.159
+++ src/interfaces/libpq/fe-exec.c      16 Jul 2004 06:59:53 -0000
@@ -613,6 +613,8 @@
         */
        if (strcmp(name, "client_encoding") == 0)
                conn->client_encoding = pg_char_to_encoding(value);
+       else if (strcmp(name, "nesting_level") == 0)
+               conn->nestingLevel = atoi(value);
        else if (strcmp(name, "server_version") == 0)
        {
                int                     cnt;
only in patch2:
unchanged:
--- src/interfaces/libpq/libpq-fe.h     24 Mar 2004 03:44:59 -0000      1.104
+++ src/interfaces/libpq/libpq-fe.h     16 Jul 2004 06:37:06 -0000
@@ -245,6 +245,7 @@
 extern char *PQoptions(const PGconn *conn);
 extern ConnStatusType PQstatus(const PGconn *conn);
 extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
+extern int     PQnestingLevel(const PGconn *conn);
 extern const char *PQparameterStatus(const PGconn *conn,
                                  const char *paramName);
 extern int     PQprotocolVersion(const PGconn *conn);
only in patch2:
unchanged:
--- src/interfaces/libpq/libpq-int.h    31 May 2004 18:42:40 -0000      1.88
+++ src/interfaces/libpq/libpq-int.h    16 Jul 2004 06:36:07 -0000
@@ -265,6 +265,7 @@
        PGAsyncStatusType asyncStatus;
        PGTransactionStatusType xactStatus;
        /* note: xactStatus never changes to ACTIVE */
+       int                     nestingLevel;   /* transaction nesting level */
        bool            nonblocking;    /* whether this connection is using
                                                                 * nonblock sending 
semantics */
        bool            ext_query;              /* was our last query sent with 
extended
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
      joining column's datatypes do not match

Reply via email to