? build.local.properties ? xa-getConnection-fix.patch ? xa2.patch Index: org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java =================================================================== RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java,v retrieving revision 1.2 diff -c -r1.2 AbstractJdbc23PooledConnection.java *** org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java 10 Sep 2007 08:38:15 -0000 1.2 --- org/postgresql/ds/jdbc23/AbstractJdbc23PooledConnection.java 13 Nov 2007 18:11:32 -0000 *************** *** 137,143 **** } con.clearWarnings(); } ! con.setAutoCommit(autoCommit); } catch (SQLException sqlException) { --- 137,149 ---- } con.clearWarnings(); } ! /* ! * 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) { Index: org/postgresql/test/xa/XADataSourceTest.java =================================================================== RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/test/xa/XADataSourceTest.java,v retrieving revision 1.9 diff -c -r1.9 XADataSourceTest.java *** org/postgresql/test/xa/XADataSourceTest.java 6 Jul 2007 20:32:43 -0000 1.9 --- org/postgresql/test/xa/XADataSourceTest.java 13 Nov 2007 18:11:32 -0000 *************** *** 258,272 **** --- 258,302 ---- 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); Index: org/postgresql/xa/PGXAConnection.java =================================================================== RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/xa/PGXAConnection.java,v retrieving revision 1.12 diff -c -r1.12 PGXAConnection.java *** org/postgresql/xa/PGXAConnection.java 27 Jul 2007 10:15:39 -0000 1.12 --- org/postgresql/xa/PGXAConnection.java 13 Nov 2007 18:11:32 -0000 *************** *** 81,98 **** public Connection getConnection() throws SQLException { 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); return conn; } --- 81,97 ---- 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. ! if(state == STATE_IDLE) ! conn.setAutoCommit(true); return conn; }