? xa-getConnection-fix.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 16:41:27 -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 16:41:27 -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 transaction_timeout() from 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 transaction_timestamp()");
+         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 16:41:28 -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;
      }
