List:Commits« Previous MessageNext Message »
From:mmatthews Date:February 15 2006 10:06pm
Subject:Connector/J commit: r4936 - in branches: branch_5_0/connector-j/src/com/mysql/jdbc branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional branch_5_0...
View as plain text  
Added:
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java
Modified:
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/ReplicationConnection.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/SQLError.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
   branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java
   branches/branch_5_1/connector-j/CHANGES
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/Connection.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/SQLError.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
   branches/branch_5_1/connector-j/src/testsuite/simple/XATest.java
Log:
Fixed BUG#17401 - Can't use XAConnection for local transactions when
      no global transaction is in progress.

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -1231,6 +1231,9 @@
 	/** Has this connection been closed? */
 	private boolean isClosed = true;
 
+	/** Is this connection associated with a global tx? */
+	private boolean isInGlobalTx = false;
+	
 	/** Is this connection running inside a JDK-1.3 VM? */
 	private boolean isRunningOnJDK13 = false;
 	
@@ -5445,4 +5448,12 @@
 	protected boolean isRunningOnJDK13() {
 		return this.isRunningOnJDK13;
 	}
+	
+	public boolean isInGlobalTx() {
+		return this.isInGlobalTx;
+	}
+
+	public void setInGlobalTx(boolean flag) {
+		this.isInGlobalTx = flag;
+	}
 }

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -624,6 +624,8 @@
 	public final static int ER_WRONG_VALUE_COUNT_ON_ROW = 1136;
 
 	public final static int ER_WRONG_VALUE_FOR_VAR = 1231;
+	
+	public final static int ER_XA_RMERR = 1401;
 
 	public final static int ER_YES = 1003;
 

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/ReplicationConnection.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/ReplicationConnection.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/ReplicationConnection.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -379,9 +379,13 @@
 	 */
 	public synchronized void setReadOnly(boolean readOnly) throws SQLException {
 		if (readOnly) {
-			switchToSlavesConnection();
+			if (currentConnection != slavesConnection) {
+				switchToSlavesConnection();
+			}
 		} else {
-			switchToMasterConnection();
+			if (currentConnection != masterConnection) {
+				switchToMasterConnection();
+			}
 		}
 	}
 
@@ -425,60 +429,51 @@
 	}
 
 	private synchronized void switchToMasterConnection() throws SQLException {
-		String slaveCatalog = this.slavesConnection.getCatalog();
-		String masterCatalog = this.masterConnection.getCatalog();
-
-		if (slaveCatalog != null && !slaveCatalog.equals(masterCatalog)) {
-			this.masterConnection.setCatalog(slaveCatalog);
-		} else if (masterCatalog != null) {
-			this.masterConnection.setCatalog(masterCatalog);
-		}
-
-		boolean slavesAutoCommit = this.slavesConnection.getAutoCommit();
-
-		if (this.masterConnection.getAutoCommit() != slavesAutoCommit) {
-			this.masterConnection.setAutoCommit(slavesAutoCommit);
-		}
-
-		int slavesTransactionIsolation = this.slavesConnection
-				.getTransactionIsolation();
-
-		if (this.masterConnection.getTransactionIsolation() != slavesTransactionIsolation) {
-			this.masterConnection
-					.setTransactionIsolation(slavesTransactionIsolation);
-		}
-
-		this.currentConnection = this.masterConnection;
+		swapConnections(this.masterConnection, this.slavesConnection);
 	}
 
 	private synchronized void switchToSlavesConnection() throws SQLException {
-		String slaveCatalog = this.slavesConnection.getCatalog();
-		String masterCatalog = this.masterConnection.getCatalog();
+		swapConnections(this.slavesConnection, this.masterConnection);
+	}
+	
+	/**
+	 * Swaps current context (catalog, autocommit and txn_isolation) from
+	 * sourceConnection to targetConnection, and makes targetConnection
+	 * the "current" connection that will be used for queries.
+	 * 
+	 * @param switchToConnection the connection to swap from
+	 * @param switchFromConnection the connection to swap to
+	 * 
+	 * @throws SQLException if an error occurs
+	 */
+	private synchronized void swapConnections(Connection switchToConnection, 
+			Connection switchFromConnection) throws SQLException {
+		String switchFromCatalog = switchFromConnection.getCatalog();
+		String switchToCatalog = switchToConnection.getCatalog();
 
-		if (masterCatalog != null && !masterCatalog.equals(slaveCatalog)) {
-			this.slavesConnection.setCatalog(masterCatalog);
-		} else if (slaveCatalog != null) {
-			this.slavesConnection.setCatalog(slaveCatalog);
+		if (switchToCatalog != null && !switchToCatalog.equals(switchFromCatalog)) {
+			switchToConnection.setCatalog(switchFromCatalog);
+		} else if (switchFromCatalog != null) {
+			switchToConnection.setCatalog(switchFromCatalog);
 		}
 
-		boolean masterAutoCommit = this.masterConnection.getAutoCommit();
-
-		if (this.slavesConnection.getAutoCommit() != masterAutoCommit) {
-			this.slavesConnection.setAutoCommit(masterAutoCommit);
+		boolean switchToAutoCommit = switchToConnection.getAutoCommit();
+		boolean switchFromConnectionAutoCommit = switchFromConnection.getAutoCommit();
+		
+		if (switchFromConnectionAutoCommit != switchToAutoCommit) {
+			switchToConnection.setAutoCommit(switchFromConnectionAutoCommit);
 		}
 
-		int masterTransactionIsolation = this.masterConnection
+		int switchToIsolation = switchToConnection
 				.getTransactionIsolation();
 
-		if (this.slavesConnection.getTransactionIsolation() != masterTransactionIsolation) {
-			this.slavesConnection
-					.setTransactionIsolation(masterTransactionIsolation);
+		int switchFromIsolation = switchFromConnection.getTransactionIsolation();
+		
+		if (switchFromIsolation != switchToIsolation) {
+			switchToConnection
+					.setTransactionIsolation(switchFromIsolation);
 		}
-		this.currentConnection = this.slavesConnection;
-
-		this.slavesConnection.setAutoCommit(this.masterConnection
-				.getAutoCommit());
-		this.slavesConnection.setTransactionIsolation(this.masterConnection
-				.getTransactionIsolation());
+		
+		this.currentConnection = switchToConnection;
 	}
 }

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/SQLError.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/SQLError.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/SQLError.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -127,6 +127,8 @@
 	public static final String SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE = "08001"; //$NON-NLS-1$
 
 	public static final String SQL_STATE_WRONG_NO_OF_PARAMETERS = "07001"; //$NON-NLS-1$
+	
+	public static final String SQL_STATE_INVALID_TRANSACTION_TERMINATION = "2D000"; //$NON_NLS-1$
 
 	private static Map sqlStateMessages;
 

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -29,6 +29,7 @@
 import java.sql.Savepoint;
 import java.sql.Statement;
 
+import com.mysql.jdbc.MysqlErrorNumbers;
 import com.mysql.jdbc.SQLError;
 
 /**
@@ -62,7 +63,7 @@
 
 	private boolean closed;
 	private boolean isForXa;
-
+	
 	/**
 	 * Construct a new LogicalHandle and set instance variables
 	 * 
@@ -84,6 +85,7 @@
 		this.isForXa = forXa;
 		
 		if (this.isForXa) {
+			setInGlobalTx(false);
 			setAutoCommit(false);
 		}
 	}
@@ -97,9 +99,10 @@
 	public void setAutoCommit(boolean autoCommit) throws SQLException {
 		checkClosed();
 
-		if (autoCommit && this.isForXa) {
+		if (autoCommit && isInGlobalTx()) {
 			throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", 
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 		
 		try {
@@ -277,6 +280,12 @@
 	public java.sql.Savepoint setSavepoint() throws SQLException {
 		checkClosed();
 
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", 
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
+		}
+		
 		try {
 			return this.mc.setSavepoint();
 		} catch (SQLException sqlException) {
@@ -292,6 +301,12 @@
 	public java.sql.Savepoint setSavepoint(String arg0) throws SQLException {
 		checkClosed();
 
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", 
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
+		}
+		
 		try {
 			return this.mc.setSavepoint(arg0);
 		} catch (SQLException sqlException) {
@@ -429,9 +444,11 @@
 	public void commit() throws SQLException {
 		checkClosed();
 		
-		if (this.isForXa) {
-			throw SQLError.createSQLException("Can't call commit() on an XAConnection",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException(
+					"Can't call commit() on an XAConnection associated with a global transaction",
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 
 		try {
@@ -733,9 +750,10 @@
 		checkClosed();
 
 
-		if (this.isForXa) {
-			throw SQLError.createSQLException("Can't call rollback() on an XAConnection",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't call rollback() on an XAConnection associated with a global transaction",
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 		
 		try {
@@ -751,9 +769,10 @@
 	public void rollback(Savepoint arg0) throws SQLException {
 		checkClosed();
 
-		if (this.isForXa) {
-			throw SQLError.createSQLException("Can't call rollback() on an XAConnection",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't call rollback() on an XAConnection associated with a global transaction",
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 		
 		try {
@@ -769,7 +788,7 @@
 				return;
 			}
 
-			if (!this.isForXa 
+			if (!isInGlobalTx() 
 					&& this.mc.getRollbackOnPooledClose()
 					&& !this.getAutoCommit()) {
 				rollback();
@@ -794,4 +813,12 @@
 			throw SQLError.createSQLException(this.invalidHandleStr);
 		}
 	}
+
+	protected boolean isInGlobalTx() {
+		return this.mc.isInGlobalTx();
+	}
+
+	protected void setInGlobalTx(boolean flag) {
+		this.mc.setInGlobalTx(flag);
+	}
 }

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -19,8 +19,6 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-
-
  */
 package com.mysql.jdbc.jdbc2.optional;
 
@@ -190,6 +188,10 @@
 	 *             XAER_RMFAIL, XAER_INVAL, and XAER_PROTO.
 	 */
 	public Xid[] recover(int flag) throws XAException {
+		return recover(this.underlyingConnection, flag);
+	}
+	
+	protected static Xid[] recover(Connection c, int flag) throws XAException {
 		switch (flag) {
 		case TMSTARTRSCAN:
 		case TMENDRSCAN:
@@ -202,7 +204,7 @@
 
 			try {
 				// TODO: Cache this for lifetime of XAConnection
-				stmt = this.underlyingConnection.createStatement();
+				stmt = c.createStatement();
 								
 				rs = stmt.executeQuery("XA RECOVER");
 
@@ -329,7 +331,11 @@
 		commandBuf.append("XA ROLLBACK ");
 		commandBuf.append(xidToString(xid));
 
-		dispatchCommand(commandBuf.toString());
+		try {
+			dispatchCommand(commandBuf.toString());
+		} finally {
+			this.underlyingConnection.setInGlobalTx(false);
+		}
 	}
 
 	/**
@@ -422,7 +428,8 @@
 		}
 
 		dispatchCommand(commandBuf.toString());
-
+		
+		this.underlyingConnection.setInGlobalTx(true);
 	}
 
 	/**
@@ -455,7 +462,11 @@
 			commandBuf.append(" ONE PHASE");
 		}
 
-		dispatchCommand(commandBuf.toString());
+		try {
+			dispatchCommand(commandBuf.toString());
+		} finally {
+			this.underlyingConnection.setInGlobalTx(false);
+		}
 	}
 
 	private ResultSet dispatchCommand(String command) throws XAException {
@@ -487,7 +498,7 @@
 		}
 	}
 
-	private XAException mapXAExceptionFromSQLException(SQLException sqlEx) {
+	protected static XAException mapXAExceptionFromSQLException(SQLException sqlEx) {
 
 		Integer xaCode = (Integer) MYSQL_ERROR_CODES_TO_XA_ERROR_CODES
 				.get(new Integer(sqlEx.getErrorCode()));
@@ -568,44 +579,4 @@
 		
 		return connToWrap;
 	}
-	
-	/**
-	 * The stock XAException class isn't too friendly (i.e. no
-	 * error messages), so we extend it a bit.
-	 */
-	class MysqlXAException extends XAException {
-		private static final long serialVersionUID = -9075817535836563004L;
-		
-		private String message;
-		private String xidAsString;
-		
-		public MysqlXAException(int errorCode, String message, String xidAsString) {
-			super(errorCode);
-			this.message = message;
-			this.xidAsString = xidAsString;
-		}
-		
-		public MysqlXAException(String message, String xidAsString) {
-			super();
-			
-			this.message = message;
-			this.xidAsString = xidAsString;
-		}
-
-		public String getMessage() {
-			String superMessage = super.getMessage();
-			StringBuffer returnedMessage = new StringBuffer();
-			
-			if (superMessage != null) {
-				returnedMessage.append(superMessage);
-				returnedMessage.append(":");
-			}
-			
-			if (this.message != null) {
-				returnedMessage.append(this.message);
-			}
-			
-			return returnedMessage.toString();
-		}
-	}
 }

Added: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as 
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL 
+ as it is applied to this software. View the full text of the 
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ */
+
+package com.mysql.jdbc.jdbc2.optional;
+
+import javax.transaction.xa.XAException;
+
+/**
+ * The stock XAException class isn't too friendly (i.e. no
+ * error messages), so we extend it a bit.
+ */
+class MysqlXAException extends XAException {
+	private static final long serialVersionUID = -9075817535836563004L;
+	
+	private String message;
+	private String xidAsString;
+	
+	public MysqlXAException(int errorCode, String message, String xidAsString) {
+		super(errorCode);
+		this.message = message;
+		this.xidAsString = xidAsString;
+	}
+	
+	public MysqlXAException(String message, String xidAsString) {
+		super();
+		
+		this.message = message;
+		this.xidAsString = xidAsString;
+	}
+
+	public String getMessage() {
+		String superMessage = super.getMessage();
+		StringBuffer returnedMessage = new StringBuffer();
+		
+		if (superMessage != null) {
+			returnedMessage.append(superMessage);
+			returnedMessage.append(":");
+		}
+		
+		if (this.message != null) {
+			returnedMessage.append(this.message);
+		}
+		
+		return returnedMessage.toString();
+	}
+}
\ No newline at end of file

Modified: branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.rmi.server.UID;
 import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Savepoint;
 
 import javax.sql.XAConnection;
 import javax.transaction.xa.XAResource;
@@ -40,7 +42,7 @@
 
 /**
  * Unit tests for our XA implementation.
- *
+ * 
  * @version $Id: $
  */
 public class XATest extends BaseTestCase {
@@ -55,10 +57,10 @@
 	}
 
 	/**
-	 * Tests that simple distributed transaction processing
-	 * works as expected.
+	 * Tests that simple distributed transaction processing works as expected.
 	 * 
-	 * @throws Exception if the test fails.
+	 * @throws Exception
+	 *             if the test fails.
 	 */
 	public void testCoordination() throws Exception {
 		if (!versionMeetsMinimum(5, 0)) {
@@ -91,6 +93,11 @@
 			xaRes1.end(xid1, XAResource.TMSUCCESS);
 			xaRes2.end(xid2, XAResource.TMSUCCESS);
 			
+			if (true) {
+				xaRes1.start(xid1, XAResource.TMJOIN);
+				xaRes2.start(xid2,  XAResource.TMJOIN);
+			}
+			
 			xaRes1.prepare(xid1);
 			xaRes2.prepare(xid2);
 			
@@ -123,12 +130,17 @@
 			
 			conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)");
 			
-			//		 ensure visibility
+			// ensure visibility
 			assertEquals("2", getSingleIndexedValueWithQuery(conn2, 1, "SELECT field1 FROM testCoordination WHERE field1=2").toString());
 			
 			xaRes1.end(xid1, XAResource.TMSUCCESS);
 			xaRes2.end(xid2, XAResource.TMSUCCESS);
 			
+			if (true) {
+				xaRes1.start(xid1, XAResource.TMJOIN);
+				xaRes2.start(xid2,  XAResource.TMJOIN);
+			}
+			
 			xaRes1.prepare(xid1);
 			xaRes2.prepare(xid2);
 			
@@ -164,7 +176,8 @@
 	/**
 	 * Tests that XA RECOVER works as expected.
 	 * 
-	 * @throws Exception if test fails
+	 * @throws Exception
+	 *             if test fails
 	 */
 	public void testRecover() throws Exception {
 		if (!versionMeetsMinimum(5, 0)) {
@@ -218,6 +231,123 @@
 		}
 	}
 
+	/**
+	 * Tests operation of local transactions on XAConnections when global
+	 * transactions are in or not in progress (follows from BUG#17401).
+	 * 
+	 * @throws Exception
+	 *             if the testcase fails
+	 */
+	public void testLocalTransaction() throws Exception {
+
+		if (!versionMeetsMinimum(5, 0) || isRunningOnJdk131()) {
+			return;
+		}
+
+		createTable("testLocalTransaction", "(field1 int) ENGINE=InnoDB");
+
+		Connection conn1 = null;
+
+		XAConnection xaConn1 = null;
+
+		try {
+			xaConn1 = getXAConnection();
+			XAResource xaRes1 = xaConn1.getXAResource();
+			conn1 = xaConn1.getConnection();
+			assertEquals(false, conn1.getAutoCommit());
+			conn1.setAutoCommit(true);
+			conn1.createStatement().executeUpdate(
+					"INSERT INTO testLocalTransaction VALUES (1)");
+			assertEquals("1", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+
+			conn1.createStatement().executeUpdate(
+					"TRUNCATE TABLE testLocalTransaction");
+			conn1.setAutoCommit(false);
+			conn1.createStatement().executeUpdate(
+					"INSERT INTO testLocalTransaction VALUES (2)");
+			assertEquals("2", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+			conn1.rollback();
+			assertEquals(0, getRowCount("testLocalTransaction"));
+
+			conn1.createStatement().executeUpdate(
+					"INSERT INTO testLocalTransaction VALUES (3)");
+			assertEquals("3", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+			conn1.commit();
+			assertEquals("3", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+			conn1.commit();
+			
+			Savepoint sp = conn1.setSavepoint();
+			conn1.rollback(sp);
+			sp = conn1.setSavepoint("abcd");
+			conn1.rollback(sp);
+			Savepoint spSaved = sp;
+			
+			Xid xid = createXid();
+			xaRes1.start(xid, XAResource.TMNOFLAGS);
+
+			try {
+				try {
+					conn1.setAutoCommit(true);
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+
+				try {
+					conn1.commit();
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+
+				try {
+					conn1.rollback();
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+				
+				try {
+					sp = conn1.setSavepoint();
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+			
+				try {
+					conn1.rollback(spSaved);
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+				
+				try {
+					sp = conn1.setSavepoint("abcd");
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+				
+				try {
+					conn1.rollback(spSaved);
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+			} finally {
+				xaRes1.forget(xid);
+			}
+		} finally {
+			if (xaConn1 != null) {
+				xaConn1.close();
+			}
+		}
+	}
+
 	private Xid createXid() throws IOException {
 		ByteArrayOutputStream gtridOut = new ByteArrayOutputStream();
 		DataOutputStream dataOut = new DataOutputStream(gtridOut);

Modified: branches/branch_5_1/connector-j/CHANGES
===================================================================
--- branches/branch_5_1/connector-j/CHANGES	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/CHANGES	2006-02-15 22:06:32 UTC (rev 4936)
@@ -1,6 +1,13 @@
 # Changelog
 # $Id$
 
+xx-xx-06 - Version 5.1.0-alpha
+
+xx-xx-06 - Version 5.0.1-beta
+
+    - Fixed BUG#17401 - Can't use XAConnection for local transactions when
+      no global transaction is in progress.
+      
 12-23-05 - Version 5.0.0-beta
 
     - XADataSource implemented (ported from 3.2 branch which won't be 

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/Connection.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/Connection.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -358,6 +358,9 @@
 	/** Has this connection been closed? */
 	private boolean isClosed = true;
 
+	/** Is this connection associated with a global tx? */
+	private boolean isInGlobalTx = false;
+	
 	/** Is this connection running inside a JDK-1.3 VM? */
 	private boolean isRunningOnJDK13 = false;
 	
@@ -4618,4 +4621,12 @@
 
 		return this.io.versionMeetsMinimum(major, minor, subminor);
 	}
+	
+	public boolean isInGlobalTx() {
+		return this.isInGlobalTx;
+	}
+
+	public void setInGlobalTx(boolean flag) {
+		this.isInGlobalTx = flag;
+	}
 }

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlErrorNumbers.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -625,6 +625,8 @@
 
 	public final static int ER_WRONG_VALUE_FOR_VAR = 1231;
 
+	public final static int ER_XA_RMERR = 1401;
+
 	public final static int ER_YES = 1003;
 
 	public final static int ER_ZLIB_Z_BUF_ERROR = 1258;

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/SQLError.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/SQLError.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/SQLError.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -128,6 +128,8 @@
 
 	public static final String SQL_STATE_WRONG_NO_OF_PARAMETERS = "07001"; //$NON-NLS-1$
 
+	public static final String SQL_STATE_INVALID_TRANSACTION_TERMINATION = "2D000"; //$NON_NLS-1$
+
 	private static Map sqlStateMessages;
 
 	static {

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -36,6 +36,7 @@
 import java.sql.Statement;
 import java.util.Properties;
 
+import com.mysql.jdbc.MysqlErrorNumbers;
 import com.mysql.jdbc.SQLError;
 import com.mysql.jdbc.ToBeImplementedException;
 
@@ -92,6 +93,7 @@
 		this.isForXa = forXa;
 		
 		if (this.isForXa) {
+			setInGlobalTx(false);
 			setAutoCommit(false);
 		}
 	}
@@ -105,9 +107,10 @@
 	public void setAutoCommit(boolean autoCommit) throws SQLException {
 		checkClosed();
 
-		if (autoCommit && this.isForXa) {
+		if (autoCommit && isInGlobalTx()) {
 			throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", 
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 		
 		try {
@@ -285,6 +288,12 @@
 	public java.sql.Savepoint setSavepoint() throws SQLException {
 		checkClosed();
 
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", 
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
+		}
+		
 		try {
 			return this.mc.setSavepoint();
 		} catch (SQLException sqlException) {
@@ -300,6 +309,12 @@
 	public java.sql.Savepoint setSavepoint(String arg0) throws SQLException {
 		checkClosed();
 
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't set autocommit to 'true' on an XAConnection", 
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
+		}
+		
 		try {
 			return this.mc.setSavepoint(arg0);
 		} catch (SQLException sqlException) {
@@ -437,9 +452,11 @@
 	public void commit() throws SQLException {
 		checkClosed();
 		
-		if (this.isForXa) {
-			throw SQLError.createSQLException("Can't call commit() on an XAConnection",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException(
+					"Can't call commit() on an XAConnection associated with a global transaction",
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 
 		try {
@@ -741,9 +758,10 @@
 		checkClosed();
 
 
-		if (this.isForXa) {
-			throw SQLError.createSQLException("Can't call rollback() on an XAConnection",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't call rollback() on an XAConnection associated with a global transaction",
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 		
 		try {
@@ -759,9 +777,10 @@
 	public void rollback(Savepoint arg0) throws SQLException {
 		checkClosed();
 
-		if (this.isForXa) {
-			throw SQLError.createSQLException("Can't call rollback() on an XAConnection",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		if (isInGlobalTx()) {
+			throw SQLError.createSQLException("Can't call rollback() on an XAConnection associated with a global transaction",
+					SQLError.SQL_STATE_INVALID_TRANSACTION_TERMINATION, 
+					MysqlErrorNumbers.ER_XA_RMERR);
 		}
 		
 		try {
@@ -777,7 +796,7 @@
 				return;
 			}
 
-			if (!this.isForXa 
+			if (!isInGlobalTx() 
 					&& this.mc.getRollbackOnPooledClose()
 					&& !this.getAutoCommit()) {
 				rollback();
@@ -803,6 +822,14 @@
 		}
 	}
 
+	protected boolean isInGlobalTx() {
+		return this.mc.isInGlobalTx();
+	}
+
+	protected void setInGlobalTx(boolean flag) {
+		this.mc.setInGlobalTx(flag);
+	}
+	
 	public Clob createClob() throws SQLException {
 		throw new ToBeImplementedException();
 	}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -19,8 +19,6 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-
-
  */
 package com.mysql.jdbc.jdbc2.optional;
 
@@ -190,6 +188,10 @@
 	 *             XAER_RMFAIL, XAER_INVAL, and XAER_PROTO.
 	 */
 	public Xid[] recover(int flag) throws XAException {
+		return recover(this.underlyingConnection, flag);
+	}
+	
+	protected static Xid[] recover(Connection c, int flag) throws XAException {
 		switch (flag) {
 		case TMSTARTRSCAN:
 		case TMENDRSCAN:
@@ -202,7 +204,7 @@
 
 			try {
 				// TODO: Cache this for lifetime of XAConnection
-				stmt = this.underlyingConnection.createStatement();
+				stmt = c.createStatement();
 								
 				rs = stmt.executeQuery("XA RECOVER");
 
@@ -329,7 +331,11 @@
 		commandBuf.append("XA ROLLBACK ");
 		commandBuf.append(xidToString(xid));
 
-		dispatchCommand(commandBuf.toString());
+		try {
+			dispatchCommand(commandBuf.toString());
+		} finally {
+			this.underlyingConnection.setInGlobalTx(false);
+		}
 	}
 
 	/**
@@ -422,7 +428,8 @@
 		}
 
 		dispatchCommand(commandBuf.toString());
-
+		
+		this.underlyingConnection.setInGlobalTx(true);
 	}
 
 	/**
@@ -455,7 +462,11 @@
 			commandBuf.append(" ONE PHASE");
 		}
 
-		dispatchCommand(commandBuf.toString());
+		try {
+			dispatchCommand(commandBuf.toString());
+		} finally {
+			this.underlyingConnection.setInGlobalTx(false);
+		}
 	}
 
 	private ResultSet dispatchCommand(String command) throws XAException {
@@ -487,7 +498,7 @@
 		}
 	}
 
-	private XAException mapXAExceptionFromSQLException(SQLException sqlEx) {
+	protected static XAException mapXAExceptionFromSQLException(SQLException sqlEx) {
 
 		Integer xaCode = (Integer) MYSQL_ERROR_CODES_TO_XA_ERROR_CODES
 				.get(new Integer(sqlEx.getErrorCode()));
@@ -568,44 +579,4 @@
 		
 		return connToWrap;
 	}
-	
-	/**
-	 * The stock XAException class isn't too friendly (i.e. no
-	 * error messages), so we extend it a bit.
-	 */
-	class MysqlXAException extends XAException {
-		private static final long serialVersionUID = -9075817535836563004L;
-		
-		private String message;
-		private String xidAsString;
-		
-		public MysqlXAException(int errorCode, String message, String xidAsString) {
-			super(errorCode);
-			this.message = message;
-			this.xidAsString = xidAsString;
-		}
-		
-		public MysqlXAException(String message, String xidAsString) {
-			super();
-			
-			this.message = message;
-			this.xidAsString = xidAsString;
-		}
-
-		public String getMessage() {
-			String superMessage = super.getMessage();
-			StringBuffer returnedMessage = new StringBuffer();
-			
-			if (superMessage != null) {
-				returnedMessage.append(superMessage);
-				returnedMessage.append(":");
-			}
-			
-			if (this.message != null) {
-				returnedMessage.append(this.message);
-			}
-			
-			return returnedMessage.toString();
-		}
-	}
 }

Added: branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAException.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as 
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL 
+ as it is applied to this software. View the full text of the 
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ */
+
+package com.mysql.jdbc.jdbc2.optional;
+
+import javax.transaction.xa.XAException;
+
+/**
+ * The stock XAException class isn't too friendly (i.e. no
+ * error messages), so we extend it a bit.
+ */
+class MysqlXAException extends XAException {
+	private static final long serialVersionUID = -9075817535836563004L;
+	
+	private String message;
+	private String xidAsString;
+	
+	public MysqlXAException(int errorCode, String message, String xidAsString) {
+		super(errorCode);
+		this.message = message;
+		this.xidAsString = xidAsString;
+	}
+	
+	public MysqlXAException(String message, String xidAsString) {
+		super();
+		
+		this.message = message;
+		this.xidAsString = xidAsString;
+	}
+
+	public String getMessage() {
+		String superMessage = super.getMessage();
+		StringBuffer returnedMessage = new StringBuffer();
+		
+		if (superMessage != null) {
+			returnedMessage.append(superMessage);
+			returnedMessage.append(":");
+		}
+		
+		if (this.message != null) {
+			returnedMessage.append(this.message);
+		}
+		
+		return returnedMessage.toString();
+	}
+}
\ No newline at end of file

Modified: branches/branch_5_1/connector-j/src/testsuite/simple/XATest.java
===================================================================
--- branches/branch_5_1/connector-j/src/testsuite/simple/XATest.java	2006-02-15 01:01:48 UTC (rev 4935)
+++ branches/branch_5_1/connector-j/src/testsuite/simple/XATest.java	2006-02-15 22:06:32 UTC (rev 4936)
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.rmi.server.UID;
 import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Savepoint;
 
 import javax.sql.XAConnection;
 import javax.transaction.xa.XAResource;
@@ -40,7 +42,7 @@
 
 /**
  * Unit tests for our XA implementation.
- *
+ * 
  * @version $Id: $
  */
 public class XATest extends BaseTestCase {
@@ -55,10 +57,10 @@
 	}
 
 	/**
-	 * Tests that simple distributed transaction processing
-	 * works as expected.
+	 * Tests that simple distributed transaction processing works as expected.
 	 * 
-	 * @throws Exception if the test fails.
+	 * @throws Exception
+	 *             if the test fails.
 	 */
 	public void testCoordination() throws Exception {
 		if (!versionMeetsMinimum(5, 0)) {
@@ -91,6 +93,11 @@
 			xaRes1.end(xid1, XAResource.TMSUCCESS);
 			xaRes2.end(xid2, XAResource.TMSUCCESS);
 			
+			if (true) {
+				xaRes1.start(xid1, XAResource.TMJOIN);
+				xaRes2.start(xid2,  XAResource.TMJOIN);
+			}
+			
 			xaRes1.prepare(xid1);
 			xaRes2.prepare(xid2);
 			
@@ -123,12 +130,17 @@
 			
 			conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)");
 			
-			//		 ensure visibility
+			// ensure visibility
 			assertEquals("2", getSingleIndexedValueWithQuery(conn2, 1, "SELECT field1 FROM testCoordination WHERE field1=2").toString());
 			
 			xaRes1.end(xid1, XAResource.TMSUCCESS);
 			xaRes2.end(xid2, XAResource.TMSUCCESS);
 			
+			if (true) {
+				xaRes1.start(xid1, XAResource.TMJOIN);
+				xaRes2.start(xid2,  XAResource.TMJOIN);
+			}
+			
 			xaRes1.prepare(xid1);
 			xaRes2.prepare(xid2);
 			
@@ -164,7 +176,8 @@
 	/**
 	 * Tests that XA RECOVER works as expected.
 	 * 
-	 * @throws Exception if test fails
+	 * @throws Exception
+	 *             if test fails
 	 */
 	public void testRecover() throws Exception {
 		if (!versionMeetsMinimum(5, 0)) {
@@ -218,6 +231,123 @@
 		}
 	}
 
+	/**
+	 * Tests operation of local transactions on XAConnections when global
+	 * transactions are in or not in progress (follows from BUG#17401).
+	 * 
+	 * @throws Exception
+	 *             if the testcase fails
+	 */
+	public void testLocalTransaction() throws Exception {
+
+		if (!versionMeetsMinimum(5, 0) || isRunningOnJdk131()) {
+			return;
+		}
+
+		createTable("testLocalTransaction", "(field1 int) ENGINE=InnoDB");
+
+		Connection conn1 = null;
+
+		XAConnection xaConn1 = null;
+
+		try {
+			xaConn1 = getXAConnection();
+			XAResource xaRes1 = xaConn1.getXAResource();
+			conn1 = xaConn1.getConnection();
+			assertEquals(false, conn1.getAutoCommit());
+			conn1.setAutoCommit(true);
+			conn1.createStatement().executeUpdate(
+					"INSERT INTO testLocalTransaction VALUES (1)");
+			assertEquals("1", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+
+			conn1.createStatement().executeUpdate(
+					"TRUNCATE TABLE testLocalTransaction");
+			conn1.setAutoCommit(false);
+			conn1.createStatement().executeUpdate(
+					"INSERT INTO testLocalTransaction VALUES (2)");
+			assertEquals("2", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+			conn1.rollback();
+			assertEquals(0, getRowCount("testLocalTransaction"));
+
+			conn1.createStatement().executeUpdate(
+					"INSERT INTO testLocalTransaction VALUES (3)");
+			assertEquals("3", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+			conn1.commit();
+			assertEquals("3", getSingleIndexedValueWithQuery(conn1, 1,
+					"SELECT field1 FROM testLocalTransaction").toString());
+			conn1.commit();
+			
+			Savepoint sp = conn1.setSavepoint();
+			conn1.rollback(sp);
+			sp = conn1.setSavepoint("abcd");
+			conn1.rollback(sp);
+			Savepoint spSaved = sp;
+			
+			Xid xid = createXid();
+			xaRes1.start(xid, XAResource.TMNOFLAGS);
+
+			try {
+				try {
+					conn1.setAutoCommit(true);
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+
+				try {
+					conn1.commit();
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+
+				try {
+					conn1.rollback();
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+				
+				try {
+					sp = conn1.setSavepoint();
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+			
+				try {
+					conn1.rollback(spSaved);
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+				
+				try {
+					sp = conn1.setSavepoint("abcd");
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+				
+				try {
+					conn1.rollback(spSaved);
+				} catch (SQLException sqlEx) {
+					// we expect an exception here
+					assertEquals("2D000", sqlEx.getSQLState());
+				}
+			} finally {
+				xaRes1.forget(xid);
+			}
+		} finally {
+			if (xaConn1 != null) {
+				xaConn1.close();
+			}
+		}
+	}
+
 	private Xid createXid() throws IOException {
 		ByteArrayOutputStream gtridOut = new ByteArrayOutputStream();
 		DataOutputStream dataOut = new DataOutputStream(gtridOut);

Thread
Connector/J commit: r4936 - in branches: branch_5_0/connector-j/src/com/mysql/jdbc branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional branch_5_0...mmatthews15 Feb