List:Commits« Previous MessageNext Message »
From:mmatthews Date:February 5 2007 6:44pm
Subject:Connector/J commit: r6303 - branches/branch_5_0/connector-j branches/branch_5_0/connector-j/src/com/mysql/jdbc trunk/connector-j trunk/connector-j/src...
View as plain text  
Modified:
   branches/branch_5_0/connector-j/CHANGES
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java
   trunk/connector-j/CHANGES
   trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java
   trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
   trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
   trunk/connector-j/src/com/mysql/jdbc/Statement.java
Log:
	- When using cached metadata, skip field-level metadata packets coming from
	  the server, rather than reading them and discarding them without creating
	  com.mysql.jdbc.Field instances.
	 
	- Fixed BUG#25836 - Statement execution which timed out doesn't always 
	  throw MySQLTimeoutException.
	  
	- Throw exceptions encountered during timeout to thread 
	  calling Statement.execute*(), rather than RuntimeException.

Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES	2007-02-05 16:40:02 UTC (rev 6302)
+++ branches/branch_5_0/connector-j/CHANGES	2007-02-05 18:44:10 UTC (rev 6303)
@@ -116,6 +116,16 @@
 	  returns keywords for MySQL-5.1, and doesn't distinguish between different
 	  versions of the server.
 	  
+	- When using cached metadata, skip field-level metadata packets coming from
+	  the server, rather than reading them and discarding them without creating
+	  com.mysql.jdbc.Field instances.
+	 
+	- Fixed BUG#25836 - Statement execution which timed out doesn't always 
+	  throw MySQLTimeoutException.
+	  
+	- Throw exceptions encountered during timeout to thread 
+	  calling Statement.execute*(), rather than RuntimeException.
+	  
 10-20-06 - Version 5.0.4
 
     - Fixed BUG#21379 - column names don't match metadata in cases 

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -1242,6 +1242,11 @@
 			
 			if (timeoutTask != null) {
 				timeoutTask.cancel();
+				
+				if (timeoutTask.caughtWhileCancelling != null) {
+					throw timeoutTask.caughtWhileCancelling;
+				}
+				
 				timeoutTask = null;
 			}
 		

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -1176,6 +1176,11 @@
 				
 				if (timeoutTask != null) {
 					timeoutTask.cancel();
+					
+					if (timeoutTask.caughtWhileCancelling != null) {
+						throw timeoutTask.caughtWhileCancelling;
+					}
+					
 					timeoutTask = null;
 				}
 				

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -71,7 +71,8 @@
 	class CancelTask extends TimerTask {
 
 		long connectionId = 0;
-
+		SQLException caughtWhileCancelling = null;
+		
 		CancelTask() throws SQLException {
 			connectionId = connection.getIO().getThreadId();
 		}
@@ -92,7 +93,14 @@
 							wasCancelled = true;
 						}
 					} catch (SQLException sqlEx) {
-						throw new RuntimeException(sqlEx.toString());
+						caughtWhileCancelling = sqlEx;
+					} catch (NullPointerException npe) {
+						// Case when connection closed while starting to cancel
+						// We can't easily synchronize this, because then one thread
+						// can't cancel() a running query
+						
+						// ignore, we shouldn't re-throw this, because the connection's
+						// already closed, so the statement has been timed out.
 					} finally {
 						if (cancelStmt != null) {
 							try {
@@ -338,6 +346,14 @@
 							+ this.connection.getIO().getThreadId());
 					this.wasCancelled = true;
 				}
+			} catch (NullPointerException npe) {
+				// Case when connection closed while starting to cancel
+				// We can't easily synchronize this, because then one thread
+				// can't cancel() a running query
+				
+				throw SQLError.createSQLException(Messages
+						.getString("Statement.49"), //$NON-NLS-1$
+						SQLError.SQL_STATE_CONNECTION_NOT_OPEN); //$NON-NLS-1$
 			} finally {
 				if (cancelStmt != null) {
 					cancelStmt.close();
@@ -551,7 +567,6 @@
 	public boolean execute(String sql) throws SQLException {
 		checkClosed();
 		
-
 		Connection locallyScopedConn = this.connection;
 		
 		synchronized (locallyScopedConn.getMutex()) {
@@ -612,7 +627,9 @@
 				rs = createResultSetUsingServerFetch(sql);
 			} else {
 				CancelTask timeoutTask = null;
-
+				
+				String oldCatalog = null;
+				
 				try {
 					if (this.timeoutInMillis != 0
 							&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
@@ -621,7 +638,7 @@
 								this.timeoutInMillis);
 					}
 
-					String oldCatalog = null;
+					
 
 					if (!locallyScopedConn.getCatalog().equals(
 							this.currentCatalog)) {
@@ -691,15 +708,15 @@
 								createStreamingResultSet(), 
 								this.currentCatalog, (cachedMetaData == null));
 					}
-
+					
 					if (timeoutTask != null) {
+						if (timeoutTask.caughtWhileCancelling != null) {
+							throw timeoutTask.caughtWhileCancelling;
+						}
+						
 						timeoutTask.cancel();
 						timeoutTask = null;
 					}
-					
-					if (oldCatalog != null) {
-						locallyScopedConn.setCatalog(oldCatalog);
-					}
 
 					synchronized (this.cancelTimeoutMutex) {
 						if (this.wasCancelled) {
@@ -707,10 +724,14 @@
 							throw new MySQLTimeoutException();
 						}
 					}
-				} finally {
+				} finally {					
 					if (timeoutTask != null) {
 						timeoutTask.cancel();
 					}
+					
+					if (oldCatalog != null) {
+						locallyScopedConn.setCatalog(oldCatalog);
+					}
 				}
 			}
 
@@ -1106,7 +1127,9 @@
 			}
 
 			CancelTask timeoutTask = null;
-
+			
+			String oldCatalog = null;
+			
 			try {
 				if (this.timeoutInMillis != 0
 						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
@@ -1115,8 +1138,6 @@
 							this.timeoutInMillis);
 				}
 
-				String oldCatalog = null;
-
 				if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
 					oldCatalog = locallyScopedConn.getCatalog();
 					locallyScopedConn.setCatalog(this.currentCatalog);
@@ -1180,14 +1201,14 @@
 				}
 
 				if (timeoutTask != null) {
+					if (timeoutTask.caughtWhileCancelling != null) {
+						throw timeoutTask.caughtWhileCancelling;
+					}
+					
 					timeoutTask.cancel();
 					timeoutTask = null;
 				}
 				
-				if (oldCatalog != null) {
-					locallyScopedConn.setCatalog(oldCatalog);
-				}
-
 				synchronized (this.cancelTimeoutMutex) {
 					if (this.wasCancelled) {
 						this.wasCancelled = false;
@@ -1198,6 +1219,10 @@
 				if (timeoutTask != null) {
 					timeoutTask.cancel();
 				}
+				
+				if (oldCatalog != null) {
+					locallyScopedConn.setCatalog(oldCatalog);
+				}
 			}
 
 			this.lastInsertId = this.results.getUpdateID();
@@ -1287,7 +1312,9 @@
 			// on the same mutex that _conn is using
 		
 			CancelTask timeoutTask = null;
-
+			
+			String oldCatalog = null;
+			
 			try {
 				if (this.timeoutInMillis != 0
 						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
@@ -1296,8 +1323,6 @@
 							this.timeoutInMillis);
 				}
 
-				String oldCatalog = null;
-
 				if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
 					oldCatalog = locallyScopedConn.getCatalog();
 					locallyScopedConn.setCatalog(this.currentCatalog);
@@ -1323,14 +1348,14 @@
 						isBatch);
 				
 				if (timeoutTask != null) {
+					if (timeoutTask.caughtWhileCancelling != null) {
+						throw timeoutTask.caughtWhileCancelling;
+					}
+					
 					timeoutTask.cancel();
 					timeoutTask = null;
 				}
 
-				if (oldCatalog != null) {
-					locallyScopedConn.setCatalog(oldCatalog);
-				}
-
 				synchronized (this.cancelTimeoutMutex) {
 					if (this.wasCancelled) {
 						this.wasCancelled = false;
@@ -1341,6 +1366,10 @@
 				if (timeoutTask != null) {
 					timeoutTask.cancel();
 				}
+				
+				if (oldCatalog != null) {
+					locallyScopedConn.setCatalog(oldCatalog);
+				}
 			}
 		}
 
@@ -1986,12 +2015,14 @@
 			}
 		}
 
+		this.isClosed = true;
+		
 		this.results = null;
 		this.connection = null;
 		this.warningChain = null;
 		this.openResults = null;
 		this.batchedGeneratedKeys = null;
-		this.isClosed = true;
+		this.cancelTimeoutMutex = null;
 	}
 
 	/**

Modified: trunk/connector-j/CHANGES
===================================================================
--- trunk/connector-j/CHANGES	2007-02-05 16:40:02 UTC (rev 6302)
+++ trunk/connector-j/CHANGES	2007-02-05 18:44:10 UTC (rev 6303)
@@ -111,7 +111,17 @@
 	  all reserved words for current MySQL version. The current fix/implementation
 	  returns keywords for MySQL-5.1, and doesn't distinguish between different
 	  versions of the server.
-	  	  	  	  
+	  
+	- When using cached metadata, skip field-level metadata packets coming from
+	  the server, rather than reading them and discarding them without creating
+	  com.mysql.jdbc.Field instances.
+	 
+	- Fixed BUG#25836 - Statement execution which timed out doesn't always 
+	  throw MySQLTimeoutException.
+	  
+	- Throw exceptions encountered during timeout to thread 
+	  calling Statement.execute*(), rather than RuntimeException.
+	  	  	  	  	  	  
 10-20-06 - Version 5.0.4
 
     - Fixed BUG#21379 - column names don't match metadata in cases 

Modified: trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ trunk/connector-j/src/com/mysql/jdbc/MysqlIO.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -366,21 +366,22 @@
         Buffer packet; // The packet from the server
         Field[] fields = null;
 
+        // Read in the column information
+        
         if (unpackFieldInfo) {
             fields = new Field[(int) columnCount];
-        }
-
-        // Read in the column information
-        for (int i = 0; i < columnCount; i++) {
-            Buffer fieldPacket = null;
-
-            fieldPacket = readPacket();
             
-            if (unpackFieldInfo) {
+            for (int i = 0; i < columnCount; i++) {
+            	Buffer fieldPacket = null;
+            
+                fieldPacket = readPacket();
                 fields[i] = unpackField(fieldPacket, false);
             }
+        } else {
+        	for (int i = 0; i < columnCount; i++) {
+        		skipPacket();
+        	}
         }
-
         packet = reuseAndReadPacket(this.reusablePacket);
 
         readServerStatusForResultSets(packet);
@@ -487,6 +488,64 @@
     }
 
     /**
+     * Reads and discards a single MySQL packet from the input stream.
+     * 
+     * @throws SQLException if the network fails while skipping the 
+     * packet.
+     */
+    protected final void skipPacket() throws SQLException {
+		try {
+
+			int lengthRead = readFully(this.mysqlInput, this.packetHeaderBuf,
+					0, 4);
+
+			if (lengthRead < 4) {
+				forceClose();
+				throw new IOException(Messages.getString("MysqlIO.1")); //$NON-NLS-1$
+			}
+
+			int packetLength = (this.packetHeaderBuf[0] & 0xff)
+					+ ((this.packetHeaderBuf[1] & 0xff) << 8)
+					+ ((this.packetHeaderBuf[2] & 0xff) << 16);
+
+			if (this.traceProtocol) {
+				StringBuffer traceMessageBuf = new StringBuffer();
+
+				traceMessageBuf.append(Messages.getString("MysqlIO.2")); //$NON-NLS-1$
+				traceMessageBuf.append(packetLength);
+				traceMessageBuf.append(Messages.getString("MysqlIO.3")); //$NON-NLS-1$
+				traceMessageBuf.append(StringUtils.dumpAsHex(
+						this.packetHeaderBuf, 4));
+
+				this.connection.getLog().logTrace(traceMessageBuf.toString());
+			}
+
+			byte multiPacketSeq = this.packetHeaderBuf[3];
+
+			if (!this.packetSequenceReset) {
+				if (this.enablePacketDebug && this.checkPacketSequence) {
+					checkPacketSequencing(multiPacketSeq);
+				}
+			} else {
+				this.packetSequenceReset = false;
+			}
+
+			this.readPacketSequence = multiPacketSeq;
+
+			this.mysqlInput.skip(packetLength);
+		} catch (IOException ioEx) {
+			throw new CommunicationsException(this.connection,
+					this.lastPacketSentTimeMs, ioEx);
+		} catch (OutOfMemoryError oom) {
+			try {
+				this.connection.realClose(false, false, true, oom);
+			} finally {
+				throw oom;
+			}
+		}
+	}
+    
+    /**
      * Read one packet from the MySQL server
      *
      * @return the packet from the server.

Modified: trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -1253,7 +1253,9 @@
 			boolean queryIsSelectOnly, boolean unpackFields, Field[] metadataFromCache,
 			boolean isBatch)
 			throws SQLException {
-		this.wasCancelled = false;
+		synchronized (this.cancelTimeoutMutex) {
+			this.wasCancelled = false;
+		}
 		
 		Connection locallyScopedConnection= this.connection;
 		
@@ -1278,12 +1280,19 @@
 			
 			if (timeoutTask != null) {
 				timeoutTask.cancel();
+				
+				if (timeoutTask.caughtWhileCancelling != null) {
+					throw timeoutTask.caughtWhileCancelling;
+				}
+				
 				timeoutTask = null;
 			}
 		
-			if (this.wasCancelled) {
-				this.wasCancelled = false;
-				throw new MySQLTimeoutException();
+			synchronized (this.cancelTimeoutMutex) {
+				if (this.wasCancelled) {
+					this.wasCancelled = false;
+					throw new MySQLTimeoutException();
+				}
 			}
 		} finally {
 			if (timeoutTask != null) {

Modified: trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -1175,7 +1175,9 @@
 				begin = System.currentTimeMillis();
 			}
 
-			this.wasCancelled = false;
+			synchronized (this.cancelTimeoutMutex) {
+				this.wasCancelled = false;
+			}
 			
 			CancelTask timeoutTask = null;
 
@@ -1192,12 +1194,19 @@
 				
 				if (timeoutTask != null) {
 					timeoutTask.cancel();
+					
+					if (timeoutTask.caughtWhileCancelling != null) {
+						throw timeoutTask.caughtWhileCancelling;
+					}
+					
 					timeoutTask = null;
 				}
 				
-				if (this.wasCancelled) {
-					this.wasCancelled = false;
-					throw new MySQLTimeoutException();
+				synchronized (this.cancelTimeoutMutex) {
+					if (this.wasCancelled) {
+						this.wasCancelled = false;
+						throw new MySQLTimeoutException();
+					}
 				}
 			
 				this.connection.incrementNumberOfPreparedExecutes();

Modified: trunk/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Statement.java	2007-02-05 16:40:02 UTC (rev 6302)
+++ trunk/connector-j/src/com/mysql/jdbc/Statement.java	2007-02-05 18:44:10 UTC (rev 6303)
@@ -70,7 +70,8 @@
 	class CancelTask extends TimerTask {
 
 		long connectionId = 0;
-
+		SQLException caughtWhileCancelling = null;
+		
 		CancelTask() throws SQLException {
 			connectionId = connection.getIO().getThreadId();
 		}
@@ -84,12 +85,21 @@
 					java.sql.Statement cancelStmt = null;
 
 					try {
-						cancelConn = connection.duplicate();
-						cancelStmt = cancelConn.createStatement();
-						cancelStmt.execute("KILL QUERY " + connectionId);
-						wasCancelled = true;
+						synchronized (cancelTimeoutMutex) {
+							cancelConn = connection.duplicate();
+							cancelStmt = cancelConn.createStatement();
+							cancelStmt.execute("KILL QUERY " + connectionId);
+							wasCancelled = true;
+						}
 					} catch (SQLException sqlEx) {
-						throw new RuntimeException(sqlEx.toString());
+						caughtWhileCancelling = sqlEx;
+					} catch (NullPointerException npe) {
+						// Case when connection closed while starting to cancel
+						// We can't easily synchronize this, because then one thread
+						// can't cancel() a running query
+						
+						// ignore, we shouldn't re-throw this, because the connection's
+						// already closed, so the statement has been timed out.
 					} finally {
 						if (cancelStmt != null) {
 							try {
@@ -114,6 +124,11 @@
 		}
 	}
 
+	/** Mutex to prevent race between returning query results and noticing
+    that we're timed-out or cancelled. */
+
+	protected Object cancelTimeoutMutex = new Object();
+
 	/** Used to generate IDs when profiling. */
 	protected static int statementCounter = 1;
 
@@ -544,11 +559,12 @@
 	public boolean execute(String sql) throws SQLException {
 		checkClosed();
 		
-
 		Connection locallyScopedConn = this.connection;
 		
 		synchronized (locallyScopedConn.getMutex()) {
-			this.wasCancelled = false;
+			synchronized (this.cancelTimeoutMutex) {
+				this.wasCancelled = false;
+			}
 	
 			checkNullOrEmptyQuery(sql);
 	
@@ -603,7 +619,9 @@
 				rs = createResultSetUsingServerFetch(sql);
 			} else {
 				CancelTask timeoutTask = null;
-
+				
+				String oldCatalog = null;
+				
 				try {
 					if (this.timeoutInMillis != 0
 							&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
@@ -612,7 +630,7 @@
 								this.timeoutInMillis);
 					}
 
-					String oldCatalog = null;
+					
 
 					if (!locallyScopedConn.getCatalog().equals(
 							this.currentCatalog)) {
@@ -624,7 +642,7 @@
 					// Check if we have cached metadata for this query...
 					//
 					if (locallyScopedConn.getCacheResultSetMetadata()) {
-						cachedMetaData = getCachedMetaData(sql);
+						cachedMetaData = locallyScopedConn.getCachedMetaData(sql);
 					}
 
 					//
@@ -682,24 +700,30 @@
 								createStreamingResultSet(), 
 								this.currentCatalog, (cachedMetaData == null));
 					}
-
+					
 					if (timeoutTask != null) {
+						if (timeoutTask.caughtWhileCancelling != null) {
+							throw timeoutTask.caughtWhileCancelling;
+						}
+						
 						timeoutTask.cancel();
 						timeoutTask = null;
 					}
-					
-					if (oldCatalog != null) {
-						locallyScopedConn.setCatalog(oldCatalog);
-					}
 
-					if (this.wasCancelled) {
-						this.wasCancelled = false;
-						throw new MySQLTimeoutException();
+					synchronized (this.cancelTimeoutMutex) {
+						if (this.wasCancelled) {
+							this.wasCancelled = false;
+							throw new MySQLTimeoutException();
+						}
 					}
-				} finally {
+				} finally {					
 					if (timeoutTask != null) {
 						timeoutTask.cancel();
 					}
+					
+					if (oldCatalog != null) {
+						locallyScopedConn.setCatalog(oldCatalog);
+					}
 				}
 			}
 
@@ -712,11 +736,11 @@
 
 				if (rs.reallyResult()) {
 					if (cachedMetaData != null) {
-						initializeResultsMetadataFromCache(sql, cachedMetaData,
+						locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData,
 								this.results);
 					} else {
 						if (this.connection.getCacheResultSetMetadata()) {
-							initializeResultsMetadataFromCache(sql,
+							locallyScopedConn.initializeResultsMetadataFromCache(sql,
 									null /* will be created */, this.results);
 						}
 					}
@@ -726,7 +750,7 @@
 			return ((rs != null) && rs.reallyResult());
 		}
 	}
-
+	
 	/**
 	 * @see Statement#execute(String, int)
 	 */
@@ -1049,12 +1073,12 @@
 		Connection locallyScopedConn = this.connection;
 		
 		synchronized (locallyScopedConn.getMutex()) {
-			this.wasCancelled = false;
+			synchronized (this.cancelTimeoutMutex) {
+				this.wasCancelled = false;
+			}
 	
 			checkNullOrEmptyQuery(sql);
-	
-			
-	
+
 			if (this.doEscapeProcessing) {
 				Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
 						locallyScopedConn.serverSupportsConvertFn(), this.connection);
@@ -1092,7 +1116,9 @@
 			}
 
 			CancelTask timeoutTask = null;
-
+			
+			String oldCatalog = null;
+			
 			try {
 				if (this.timeoutInMillis != 0
 						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
@@ -1101,8 +1127,6 @@
 							this.timeoutInMillis);
 				}
 
-				String oldCatalog = null;
-
 				if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
 					oldCatalog = locallyScopedConn.getCatalog();
 					locallyScopedConn.setCatalog(this.currentCatalog);
@@ -1112,7 +1136,7 @@
 				// Check if we have cached metadata for this query...
 				//
 				if (locallyScopedConn.getCacheResultSetMetadata()) {
-					cachedMetaData = getCachedMetaData(sql);
+					cachedMetaData = locallyScopedConn.getCachedMetaData(sql);
 				}
 
 				if (locallyScopedConn.useMaxRows()) {
@@ -1166,45 +1190,42 @@
 				}
 
 				if (timeoutTask != null) {
+					if (timeoutTask.caughtWhileCancelling != null) {
+						throw timeoutTask.caughtWhileCancelling;
+					}
+					
 					timeoutTask.cancel();
 					timeoutTask = null;
 				}
 				
-				if (oldCatalog != null) {
-					locallyScopedConn.setCatalog(oldCatalog);
+				synchronized (this.cancelTimeoutMutex) {
+					if (this.wasCancelled) {
+						this.wasCancelled = false;
+						throw new MySQLTimeoutException();
+					}
 				}
-
-				if (this.wasCancelled) {
-					this.wasCancelled = false;
-
-					throw new MySQLTimeoutException();
-				}
 			} finally {
 				if (timeoutTask != null) {
 					timeoutTask.cancel();
 				}
+				
+				if (oldCatalog != null) {
+					locallyScopedConn.setCatalog(oldCatalog);
+				}
 			}
 
 			this.lastInsertId = this.results.getUpdateID();
 
-			/*
-			 * if (!this.results.reallyResult()) { if
-			 * (!this.connection.getAutoCommit()) { this.connection.rollback(); }
-			 * 
-			 * throw
-			 * SQLError.createSQLException(Messages.getString("Statement.40"),
-			 * //$NON-NLS-1$ SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ }
-			 */
 			if (cachedMetaData != null) {
-				initializeResultsMetadataFromCache(sql, cachedMetaData,
+				locallyScopedConn.initializeResultsMetadataFromCache(sql, cachedMetaData,
 						this.results);
 			} else {
 				if (this.connection.getCacheResultSetMetadata()) {
-					initializeResultsMetadataFromCache(sql,
+					locallyScopedConn.initializeResultsMetadataFromCache(sql,
 							null /* will be created */, this.results);
 				}
 			}
-
+			
 			return this.results;
 		}
 	}
@@ -1229,18 +1250,20 @@
 	}
 
 	protected int executeUpdate(String sql, boolean isBatch)
-			throws SQLException {
+		throws SQLException {
 		checkClosed();
-		
+
 		Connection locallyScopedConn = this.connection;
-		
+
 		char firstStatementChar = StringUtils.firstNonWsCharUc(sql);
 
 		ResultSet rs = null;
 
 		synchronized (locallyScopedConn.getMutex()) {
-			this.wasCancelled = false;
-	
+			synchronized (this.cancelTimeoutMutex) {
+				this.wasCancelled = false;
+			}
+
 			checkNullOrEmptyQuery(sql);
 
 			if (this.doEscapeProcessing) {
@@ -1253,32 +1276,34 @@
 					sql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
 				}
 			}
-			
+
 			if (locallyScopedConn.isReadOnly()) {
 				throw SQLError.createSQLException(Messages
 						.getString("Statement.42") //$NON-NLS-1$
 						+ Messages.getString("Statement.43"), //$NON-NLS-1$
 						SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
 			}
-	
+
 			if (StringUtils.startsWithIgnoreCaseAndWs(sql, "select")) { //$NON-NLS-1$
 				throw SQLError.createSQLException(Messages
 						.getString("Statement.46"), //$NON-NLS-1$
-						"01S03"); //$NON-NLS-1$
+				"01S03"); //$NON-NLS-1$
 			}
-	
+
 			if (this.results != null) {
 				if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
 					this.results.realClose(false);
 				}
 			}
-	
+
 			// The checking and changing of catalogs
 			// must happen in sequence, so synchronize
 			// on the same mutex that _conn is using
-		
+
 			CancelTask timeoutTask = null;
 
+			String oldCatalog = null;
+
 			try {
 				if (this.timeoutInMillis != 0
 						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
@@ -1287,8 +1312,6 @@
 							this.timeoutInMillis);
 				}
 
-				String oldCatalog = null;
-
 				if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
 					oldCatalog = locallyScopedConn.getCatalog();
 					locallyScopedConn.setCatalog(this.currentCatalog);
@@ -1312,24 +1335,30 @@
 						this.currentCatalog,
 						true /* force read of field info on DML */,
 						isBatch);
-				
+
 				if (timeoutTask != null) {
+					if (timeoutTask.caughtWhileCancelling != null) {
+						throw timeoutTask.caughtWhileCancelling;
+					}
+
 					timeoutTask.cancel();
 					timeoutTask = null;
 				}
 
-				if (oldCatalog != null) {
-					locallyScopedConn.setCatalog(oldCatalog);
+				synchronized (this.cancelTimeoutMutex) {
+					if (this.wasCancelled) {
+						this.wasCancelled = false;
+						throw new MySQLTimeoutException();
+					}
 				}
-
-				if (this.wasCancelled) {
-					this.wasCancelled = false;
-					throw new MySQLTimeoutException();
-				}
 			} finally {
 				if (timeoutTask != null) {
 					timeoutTask.cancel();
 				}
+
+				if (oldCatalog != null) {
+					locallyScopedConn.setCatalog(oldCatalog);
+				}
 			}
 		}
 
@@ -1352,6 +1381,7 @@
 		return truncatedUpdateCount;
 	}
 
+
 	/**
 	 * @see Statement#executeUpdate(String, int)
 	 */
@@ -2041,12 +2071,14 @@
 			}
 		}
 
+		this.isClosed = true;
+		
 		this.results = null;
 		this.connection = null;
 		this.warningChain = null;
 		this.openResults = null;
 		this.batchedGeneratedKeys = null;
-		this.isClosed = true;
+		this.cancelTimeoutMutex = null;
 	}
 
 	/**

Thread
Connector/J commit: r6303 - branches/branch_5_0/connector-j branches/branch_5_0/connector-j/src/com/mysql/jdbc trunk/connector-j trunk/connector-j/src...mmatthews5 Feb