[libpostgresql-jdbc-java] 08/12: Multiple calls to XAConnection.getConnection within the same user transaction ended up restarting the transaction on the server side as a result of manipulating the autocommit state. When retrieving a Connection, we must pay attention to whether a user transaction is in progress when setting the autocommit state.

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Mon Jan 9 10:20:28 UTC 2017


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to tag REL8_2_507
in repository libpostgresql-jdbc-java.

commit 1a677d05ae9828155960f22d2c23ec05ec7be17d
Author: Kris Jurka <books at ejurka.com>
Date:   Wed Nov 14 22:03:47 2007 +0000

    Multiple calls to XAConnection.getConnection within the same user
    transaction ended up restarting the transaction on the server side
    as a result of manipulating the autocommit state.  When retrieving
    a Connection, we must pay attention to whether a user transaction
    is in progress when setting the autocommit state.
    
    This only fixes the case where a close call is interspersed between
    the getConnection calls.  Without the close call, the second
    getConnection performs a silent rollback.  Even with the close, this
    is dodgy behavior from the client and we expect it not to happen,
    but it would be better if we actually forbade it.
    
    Heikki Linnakangas
---
 .../ds/jdbc23/AbstractJdbc23PooledConnection.java  |  8 +++++-
 org/postgresql/test/xa/XADataSourceTest.java       | 30 ++++++++++++++++++++++
 org/postgresql/xa/PGXAConnection.java              | 11 ++++----
 3 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java b/org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java
index 69141fa..d6bd9a2 100644
--- a/org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java
+++ b/org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java
@@ -137,7 +137,13 @@ public abstract class AbstractJdbc23PooledConnection
                 }
                 con.clearWarnings();
             }
-            con.setAutoCommit(autoCommit);
+            /*
+             * In XA-mode, autocommit is handled in PGXAConnection,
+             * because it depends on whether an XA-transaction is open
+             * or not
+             */
+            if (!isXA)
+                con.setAutoCommit(autoCommit);
         }
         catch (SQLException sqlException)
         {
diff --git a/org/postgresql/test/xa/XADataSourceTest.java b/org/postgresql/test/xa/XADataSourceTest.java
index 8bc9f0a..3b1bc1d 100644
--- a/org/postgresql/test/xa/XADataSourceTest.java
+++ b/org/postgresql/test/xa/XADataSourceTest.java
@@ -258,15 +258,45 @@ public class XADataSourceTest extends TestCase {
 
         xaRes.start(xid, XAResource.TMNOFLAGS);
 
+        conn.createStatement().executeQuery("SELECT * FROM testxa1");
+
+        java.sql.Timestamp ts1 = getTransactionTimestamp(conn);
+
+        conn.close();
         conn = xaconn.getConnection();
         assertFalse(conn.getAutoCommit());
 
+        java.sql.Timestamp ts2 = getTransactionTimestamp(conn);
+
+        /* Check that we're still in the same transaction. 
+         * close+getConnection() should not rollback the XA-transaction
+         * implicitly.
+         */
+        assertEquals(ts1, ts2);
+
         xaRes.end(xid, XAResource.TMSUCCESS);
         xaRes.prepare(xid);
         xaRes.rollback(xid);
         assertTrue(conn.getAutoCommit());
     }
 
+    /**
+     * Get the time the current transaction was started from the server. 
+     *
+     * This can be used to check that transaction doesn't get committed/
+     * rolled back inadvertently, by calling this once before and after the
+     * suspected piece of code, and check that they match. It's a bit iffy,
+     * conceivably you might get the same timestamp anyway if the
+     * suspected piece of code runs fast enough, and/or the server clock
+     * is very coarse grained. But it'll do for testing purposes.
+     */
+    private static java.sql.Timestamp getTransactionTimestamp(Connection conn) throws SQLException
+    {
+        ResultSet rs = conn.createStatement().executeQuery("SELECT now()");
+        rs.next();
+        return rs.getTimestamp(1);
+    }
+
     public void testEndThenJoin() throws XAException {
         Xid xid = new CustomXid(5);
 
diff --git a/org/postgresql/xa/PGXAConnection.java b/org/postgresql/xa/PGXAConnection.java
index 465c637..3b33975 100644
--- a/org/postgresql/xa/PGXAConnection.java
+++ b/org/postgresql/xa/PGXAConnection.java
@@ -82,18 +82,17 @@ public class PGXAConnection extends PGPooledConnection implements XAConnection,
 
     public Connection getConnection() throws SQLException
     {
+        if (logger.logDebug())
+            debug("PGXAConnection.getConnection called");
+
         Connection conn = super.getConnection();
 
         // When we're outside an XA transaction, autocommit
         // is supposed to be true, per usual JDBC convention.
         // When an XA transaction is in progress, it should be
         // false.
-
-        // super.getConnection rolls back any previous transaction, and resets
-        // autocommit to true, so we have to set it to false before handing the
-        // connection to the caller, if an XA transaction is active.
-        if(state == STATE_ACTIVE)
-            conn.setAutoCommit(false);
+        if(state == STATE_IDLE)
+            conn.setAutoCommit(true);
 
         return conn;
     }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libpostgresql-jdbc-java.git



More information about the pkg-java-commits mailing list