List:Commits« Previous MessageNext Message »
From:mmatthews Date:June 7 2006 2:50pm
Subject:Connector/J commit: r5364 - in branches/branch_5_0/connector-j/src: com/mysql/jdbc com/mysql/jdbc/jdbc2/optional com/mysql/jdbc/profiler testsuite/reg...
View as plain text  
Modified:
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/ConnectionProperties.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.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/MysqlPooledConnection.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/profiler/ProfileEventSink.java
   branches/branch_5_0/connector-j/src/testsuite/regression/MetaDataRegressionTest.java
   branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java
Log:
Merged 3.1.

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-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -1840,6 +1840,8 @@
 		if (versionMeetsMinimum(4, 1, 0)) {
 			configureClientCharacterSet();
 		}
+		
+		setupServerForTruncationChecks();
 	}
 
 	private void checkAndCreatePerformanceHistogram() {
@@ -4050,8 +4052,44 @@
 				setAllowMultiQueries(false);
 			}
 		}
+		
+		//
+		// Server can do this more efficiently for us
+		//
+		
+		setupServerForTruncationChecks();
 	}
 
+	private void setupServerForTruncationChecks() throws SQLException {
+		if (getJdbcCompliantTruncation()) {
+			if (versionMeetsMinimum(5, 0, 2)) {
+				String currentSqlMode = 
+					(String)this.serverVariables.get("sql_mode");
+				
+				if (currentSqlMode == null ||
+						currentSqlMode.length() == 0 ||
+						StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") == -1) {
+					StringBuffer commandBuf = new StringBuffer("SET sql_mode='");
+					
+					if (currentSqlMode != null && currentSqlMode.length() > 0) {
+						commandBuf.append(currentSqlMode);
+						commandBuf.append(",");
+					}
+					
+					commandBuf.append("STRICT_TRANS_TABLES'");
+					
+					execSQL(null,  commandBuf.toString(), -1, null,
+							java.sql.ResultSet.TYPE_FORWARD_ONLY,
+							java.sql.ResultSet.CONCUR_READ_ONLY, false,
+							this.database, true, false);
+					
+					setJdbcCompliantTruncation(false); // server's handling this for us now
+				}
+				
+			}
+		}
+	}
+
 	protected boolean isClientTzUTC() {
 		return this.isClientTzUTC;
 	}
@@ -4677,6 +4715,7 @@
 		} finally {
 			this.openStatements = null;
 			this.io = null;
+			ProfileEventSink.removeInstance(this);
 			this.isClosed = true;
 		}
 

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/ConnectionProperties.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/ConnectionProperties.java	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/ConnectionProperties.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -900,6 +900,9 @@
 					+ "(MySQL 4.1.0 and newer)?", "3.1.2", MISC_CATEGORY,
 			Integer.MIN_VALUE);
 
+	private boolean jdbcCompliantTruncationForReads = 
+		this.jdbcCompliantTruncation.getValueAsBoolean();
+	
 	private MemorySizeConnectionProperty locatorFetchBufferSize = new MemorySizeConnectionProperty(
 			"locatorFetchBufferSize",
 			1024 * 1024,
@@ -3662,4 +3665,13 @@
 	public int getPrepStmtCacheSqlLimit() {
 		return getPreparedStatementCacheSqlLimit();
 	}
+
+	protected boolean getJdbcCompliantTruncationForReads() {
+		return this.jdbcCompliantTruncationForReads;
+	}
+
+	protected void setJdbcCompliantTruncationForReads(
+			boolean jdbcCompliantTruncationForReads) {
+		this.jdbcCompliantTruncationForReads = jdbcCompliantTruncationForReads;
+	}
 }

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	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -192,10 +192,9 @@
 				if (!inQuotes && (quotedIdentifierChar != 0)
 						&& (c == quotedIdentifierChar)) {
 					inQuotedId = !inQuotedId;
-				}
-
-				// only respect quotes when not in a quoted identifier
-				if (!inQuotedId) {
+				} else if (!inQuotedId) {
+					//	only respect quotes when not in a quoted identifier
+					
 					if (inQuotes) {
 						if ((((c == '\'') || (c == '"')) && c == quoteChar)
 								&& (pre1 == '\\') && (pre2 != '\\')) {
@@ -863,6 +862,8 @@
 	private int[] executeBatchedInserts() throws SQLException {
 		String valuesClause = extractValuesClause();
 
+		Connection locallyScopedConn = this.connection;
+		
 		if (valuesClause == null) {
 			return executeBatchSerially();
 		}
@@ -882,11 +883,11 @@
 		java.sql.PreparedStatement batchedStatement = null;
 
 		if (this.retrieveGeneratedKeys) {
-			batchedStatement = this.connection.prepareStatement(
+			batchedStatement = locallyScopedConn.prepareStatement(
 					generateBatchedInsertSQL(valuesClause, numValuesPerBatch),
 					RETURN_GENERATED_KEYS);
 		} else {
-			batchedStatement = this.connection
+			batchedStatement = locallyScopedConn
 					.prepareStatement(generateBatchedInsertSQL(valuesClause,
 							numValuesPerBatch));
 		}
@@ -928,7 +929,7 @@
 
 		if (numValuesPerBatch > 0) {
 
-			batchedStatement = this.connection.prepareStatement(
+			batchedStatement = locallyScopedConn.prepareStatement(
 					generateBatchedInsertSQL(valuesClause, numValuesPerBatch),
 					RETURN_GENERATED_KEYS);
 			batchedParamIndex = 1;
@@ -1018,7 +1019,8 @@
 	 *             if an error occurs
 	 */
 	protected int[] executeBatchSerially() throws SQLException {
-
+		Connection locallyScopedConn = this.connection;
+		
 		int[] updateCounts = null;
 
 		if (this.batchedArgs != null) {
@@ -1070,7 +1072,7 @@
 					} catch (SQLException ex) {
 						updateCounts[commandIndex] = EXECUTE_FAILED;
 
-						if (this.connection.getContinueBatchOnError()) {
+						if (locallyScopedConn.getContinueBatchOnError()) {
 							sqlEx = ex;
 						} else {
 							int[] newUpdateCounts = new int[commandIndex];
@@ -1120,6 +1122,8 @@
 			throws SQLException {
 		this.wasCancelled = false;
 		
+		Connection locallyScopedConnection= this.connection;
+		
 		this.numberOfExecutions++;
 
 		ResultSet rs;
@@ -1128,13 +1132,13 @@
 
 		try {
 			if (this.timeout != 0
-					&& this.connection.versionMeetsMinimum(5, 0, 0)) {
+					&& locallyScopedConnection.versionMeetsMinimum(5, 0, 0)) {
 				timeoutTask = new CancelTask();
-				this.connection.getCancelTimer().schedule(timeoutTask, 
+				Connection.getCancelTimer().schedule(timeoutTask, 
 						this.timeout);
 			}
 			
-			rs = this.connection.execSQL(this, null, maxRowsToRetrieve, sendPacket,
+			rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket,
 				this.resultSetType, this.resultSetConcurrency,
 				createStreamingResultSet, this.currentCatalog,
 				unpackFields, isBatch);
@@ -1168,7 +1172,9 @@
 	 */
 	public java.sql.ResultSet executeQuery() throws SQLException {
 		checkClosed();
-
+		
+		Connection locallyScopedConn = this.connection;
+		
 		checkForDml(this.originalSql, this.firstCharOfStmt);
 
 		CachedResultSetMetaData cachedMetadata = null;
@@ -1177,7 +1183,7 @@
 		// So synchronize on the Connection's mutex (because
 		// even queries going through there synchronize
 		// on the same mutex.
-		synchronized (this.connection.getMutex()) {
+		synchronized (locallyScopedConn.getMutex()) {
 			clearWarnings();
 
 			this.batchedGeneratedKeys = null;
@@ -1194,19 +1200,19 @@
 
 			String oldCatalog = null;
 
-			if (!this.connection.getCatalog().equals(this.currentCatalog)) {
-				oldCatalog = this.connection.getCatalog();
-				this.connection.setCatalog(this.currentCatalog);
+			if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
+				oldCatalog = locallyScopedConn.getCatalog();
+				locallyScopedConn.setCatalog(this.currentCatalog);
 			}
 
 			//
 			// Check if we have cached metadata for this query...
 			//
-			if (this.connection.getCacheResultSetMetadata()) {
+			if (locallyScopedConn.getCacheResultSetMetadata()) {
 				cachedMetadata = getCachedMetaData(this.originalSql);
 			}
 
-			if (this.connection.useMaxRows()) {
+			if (locallyScopedConn.useMaxRows()) {
 				// If there isn't a limit clause in the SQL
 				// then limit the number of rows to return in
 				// an efficient manner. Only do this if
@@ -1219,7 +1225,7 @@
 							(cachedMetadata == null), false);
 				} else {
 					if (this.maxRows <= 0) {
-						this.connection
+						locallyScopedConn
 								.execSQL(
 										this,
 										"SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$
@@ -1227,7 +1233,7 @@
 										java.sql.ResultSet.CONCUR_READ_ONLY,
 										false, this.currentCatalog, true);
 					} else {
-						this.connection
+						locallyScopedConn
 								.execSQL(
 										this,
 										"SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, -1, null, //$NON-NLS-1$
@@ -1251,7 +1257,7 @@
 			}
 
 			if (oldCatalog != null) {
-				this.connection.setCatalog(oldCatalog);
+				locallyScopedConn.setCatalog(oldCatalog);
 			}
 		}
 
@@ -1326,8 +1332,10 @@
 			throws SQLException {
 
 		checkClosed();
+
+		Connection locallyScopedConn = this.connection;
 		
-		if (this.connection.isReadOnly()) {
+		if (locallyScopedConn.isReadOnly()) {
 			throw SQLError.createSQLException(Messages.getString("PreparedStatement.34") //$NON-NLS-1$
 					+ Messages.getString("PreparedStatement.35"), //$NON-NLS-1$
 					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
@@ -1341,7 +1349,7 @@
 		}
 
 		if (this.results != null) {
-			if (!this.connection.getHoldResultsOpenOverStatementClose()) {
+			if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
 				this.results.realClose(false);
 			}
 		}
@@ -1351,23 +1359,23 @@
 		// The checking and changing of catalogs
 		// must happen in sequence, so synchronize
 		// on the same mutex that _conn is using
-		synchronized (this.connection.getMutex()) {
+		synchronized (locallyScopedConn.getMutex()) {
 			Buffer sendPacket = fillSendPacket(batchedParameterStrings,
 					batchedParameterStreams, batchedIsStream,
 					batchedStreamLengths);
 
 			String oldCatalog = null;
 
-			if (!this.connection.getCatalog().equals(this.currentCatalog)) {
-				oldCatalog = this.connection.getCatalog();
-				this.connection.setCatalog(this.currentCatalog);
+			if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
+				oldCatalog = locallyScopedConn.getCatalog();
+				locallyScopedConn.setCatalog(this.currentCatalog);
 			}
 
 			//
 			// Only apply max_rows to selects
 			//
-			if (this.connection.useMaxRows()) {
-				this.connection.execSQL(this,
+			if (locallyScopedConn.useMaxRows()) {
+				locallyScopedConn.execSQL(this,
 						"SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$
 						java.sql.ResultSet.TYPE_FORWARD_ONLY,
 						java.sql.ResultSet.CONCUR_READ_ONLY, false,
@@ -1377,19 +1385,19 @@
 			boolean oldInfoMsgState = false;
 
 			if (this.retrieveGeneratedKeys) {
-				oldInfoMsgState = this.connection.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				oldInfoMsgState = locallyScopedConn.isReadInfoMsgEnabled();
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 			}
 
 			rs = executeInternal(-1, sendPacket, false, false, true, isReallyBatch);
 
 			if (this.retrieveGeneratedKeys) {
-				this.connection.setReadInfoMsgEnabled(oldInfoMsgState);
+				locallyScopedConn.setReadInfoMsgEnabled(oldInfoMsgState);
 				rs.setFirstCharOfQuery(this.firstCharOfStmt);
 			}
 
 			if (oldCatalog != null) {
-				this.connection.setCatalog(oldCatalog);
+				locallyScopedConn.setCatalog(oldCatalog);
 			}
 		}
 
@@ -2824,7 +2832,12 @@
 	 */
 	public void setObject(int parameterIndex, Object parameterObj,
 			int targetSqlType) throws SQLException {
-		setObject(parameterIndex, parameterObj, targetSqlType, 0);
+		if (!(parameterObj instanceof BigDecimal)) {
+			setObject(parameterIndex, parameterObj, targetSqlType, 0);
+		} else {
+			setObject(parameterIndex, parameterObj, targetSqlType,
+					((BigDecimal)parameterObj).scale());
+		}
 	}
 
 	/**

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/ResultSet.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -1163,11 +1163,17 @@
 				try {
 					val = new BigDecimal(stringVal);
 				} catch (NumberFormatException ex) {
-					throw SQLError.createSQLException(Messages
+					if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+						long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
+
+						val = new BigDecimal(valueAsLong);
+					} else {
+						throw SQLError.createSQLException(Messages
 							.getString("ResultSet.Bad_format_for_BigDecimal",
 									new Object[] { new Integer(columnIndex),
 											stringVal }),
 							SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
+						}
 				}
 
 				try {
@@ -1233,25 +1239,20 @@
 
 		if (stringVal != null) {
 			if (stringVal.length() == 0) {
-				
 				bdVal = new BigDecimal(convertToZeroLiteralStringWithEmptyCheck());
 
 				try {
-				return bdVal.setScale(scale);
+					return bdVal.setScale(scale);
 				} catch (ArithmeticException ex) {
 					try {
 						return bdVal.setScale(scale, BigDecimal.ROUND_HALF_UP);
 					} catch (ArithmeticException arEx) {
-						throw new SQLException(
-								Messages
-										.getString("ResultSet.Bad_format_for_BigDecimal____124") //$NON-NLS-1$
-										+ stringVal
-										+ Messages
-												.getString("ResultSet.___in_column__125")
-										+ columnIndex + "(" //$NON-NLS-1$
-										+ this.fields[columnIndex - 1] + ").",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-			}
+						throw new SQLException(Messages
+								.getString("ResultSet.Bad_format_for_BigDecimal",
+										new Object[] { stringVal,
+												new Integer(columnIndex) }),
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
+					}
 				}
 			}
 
@@ -1263,30 +1264,46 @@
 						return new BigDecimal(stringVal).setScale(scale,
 								BigDecimal.ROUND_HALF_UP);
 					} catch (ArithmeticException arEx) {
-						throw SQLError.createSQLException(
-								Messages
-										.getString("ResultSet.Bad_format_for_BigDecimal____166") //$NON-NLS-1$
-										+ stringVal
-										+ Messages
-												.getString("ResultSet.___in_column__167")
-										+ columnIndex + "(" //$NON-NLS-1$
-										+ this.fields[columnIndex - 1] + ").",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+						throw new SQLException(Messages
+								.getString("ResultSet.Bad_format_for_BigDecimal",
+										new Object[] { stringVal,
+												new Integer(columnIndex) }),
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
 					}
 				}
 			} catch (NumberFormatException ex) {
-				throw SQLError.createSQLException(
-						Messages
-								.getString("ResultSet.Bad_format_for_BigDecimal____166") //$NON-NLS-1$
-								+ stringVal
-								+ Messages
-										.getString("ResultSet.___in_column__167")
-								+ columnIndex + "(" //$NON-NLS-1$
-								+ this.fields[columnIndex - 1] + ").",
-						SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+					long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
+
+					try {
+						return new BigDecimal(valueAsLong).setScale(scale);
+					} catch (ArithmeticException arEx1) {
+						try {
+							return new BigDecimal(valueAsLong).setScale(scale,
+									BigDecimal.ROUND_HALF_UP);
+						} catch (ArithmeticException arEx2) {
+							throw new SQLException(Messages
+									.getString("ResultSet.Bad_format_for_BigDecimal",
+											new Object[] { stringVal,
+													new Integer(columnIndex) }),
+									SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
+						}
+					}
+				}
+				
+				if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TINY &&
+						this.connection.getTinyInt1isBit() && this.fields[columnIndex - 1].getLength() == 1) {
+					return new BigDecimal(stringVal.equalsIgnoreCase("true") ? 1 : 0).setScale(scale);
+				}
+				
+				throw new SQLException(Messages
+						.getString("ResultSet.Bad_format_for_BigDecimal",
+								new Object[] { stringVal,
+										new Integer(columnIndex) }),
+						SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
 			}
 		}
-
+		
 		return null;
 	}
 
@@ -2182,6 +2199,12 @@
 
 			return d;
 		} catch (NumberFormatException e) {
+			if (this.fields[colIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+				long valueAsLong = getNumericRepresentationOfSQLBitType(colIndex);
+				
+				return valueAsLong;
+			}
+			
 			throw SQLError.createSQLException(Messages.getString(
 					"ResultSet.Bad_format_for_number", new Object[] {
 							stringVal, new Integer(colIndex) }),
@@ -2292,8 +2315,8 @@
 				double valAsDouble = Double.parseDouble(val);
 
 				if (this.connection.getJdbcCompliantTruncation()) {
-					if (valAsDouble < Float.MIN_VALUE
-							|| valAsDouble > Float.MAX_VALUE) {
+					if (Math.abs(valAsDouble - Float.MIN_VALUE) > 1  
+							|| Math.abs(valAsDouble - Float.MAX_VALUE) > 1) {
 						throwRangeException(String.valueOf(valAsDouble),
 								columnIndex, Types.FLOAT);
 					}
@@ -2381,6 +2404,19 @@
 							; // ignore, it's not a number
 						}
 
+						if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+							long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
+							
+							if (this.connection.getJdbcCompliantTruncationForReads() &&
+									(valueAsLong < Integer.MIN_VALUE
+											|| valueAsLong > Integer.MAX_VALUE)) {
+								throwRangeException(String.valueOf(valueAsLong), columnIndex,
+										Types.INTEGER);
+							}
+							
+							return (int)valueAsLong;
+						}
+						
 						throw SQLError.createSQLException(
 								Messages
 										.getString("ResultSet.Invalid_value_for_getInt()_-____74")
@@ -2418,6 +2454,19 @@
 					; // ignore, it's not a number
 				}
 
+				if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+					long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
+					
+					if (this.connection.getJdbcCompliantTruncationForReads() &&
+							(valueAsLong < Integer.MIN_VALUE
+									|| valueAsLong > Integer.MAX_VALUE)) {
+						throwRangeException(String.valueOf(valueAsLong), columnIndex,
+								Types.INTEGER);
+					}
+					
+					return (int)valueAsLong;
+				}
+				
 				throw SQLError.createSQLException(
 						Messages
 								.getString("ResultSet.Invalid_value_for_getInt()_-____74")
@@ -2594,6 +2643,10 @@
 							// ; // ignore, it's not a number
 						}
 
+						if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+							return getNumericRepresentationOfSQLBitType(columnIndex);
+						}
+						
 						throw SQLError.createSQLException(
 								Messages
 										.getString("ResultSet.Invalid_value_for_getLong()_-____79")
@@ -3021,6 +3074,17 @@
 		Field field = this.fields[columnIndex];
 
 		switch (field.getMysqlType()) {
+		case MysqlDefs.FIELD_TYPE_BIT:
+			long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
+			
+			if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
+					(valueAsLong < Byte.MIN_VALUE
+							|| valueAsLong > Byte.MAX_VALUE)) {
+				throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
+						Types.TINYINT);
+			}
+			
+			return (byte)valueAsLong;
 		case MysqlDefs.FIELD_TYPE_TINY:
 			byte valueAsByte = ((byte[]) this.thisRow[columnIndex])[0];
 			
@@ -3094,7 +3158,7 @@
 			return (byte) valueAsDouble;
 
 		case MysqlDefs.FIELD_TYPE_LONGLONG:
-			long valueAsLong = getNativeLong(columnIndex + 1, false, true);
+			valueAsLong = getNativeLong(columnIndex + 1, false, true);
 
 			if (overflowCheck && this.connection.getJdbcCompliantTruncation()) {
 				if (valueAsLong < Byte.MIN_VALUE
@@ -3245,6 +3309,7 @@
 
 		switch (sqlType) {
 		case Types.BIT:
+			return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
 		case Types.BOOLEAN:
 			boolean booleanVal = getNativeBoolean(columnIndex);
 
@@ -3672,7 +3737,8 @@
 			return asBigInt.doubleValue();
 		case MysqlDefs.FIELD_TYPE_FLOAT:
 			return (double) getNativeFloat(columnIndex + 1);
-
+		case MysqlDefs.FIELD_TYPE_BIT:
+			return getNumericRepresentationOfSQLBitType(columnIndex + 1);
 		default:
 
 			if (this.useUsageAdvisor) {
@@ -3720,6 +3786,10 @@
 		Field f = this.fields[columnIndex];
 		
 		switch (f.getMysqlType()) {
+		case MysqlDefs.FIELD_TYPE_BIT:
+			long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
+
+			return valueAsLong;
 		case MysqlDefs.FIELD_TYPE_DOUBLE:
 			double valueAsDouble = getNativeDouble(columnIndex + 1);
 			
@@ -3752,7 +3822,7 @@
 			
 			return (float) getNativeLong(columnIndex + 1);
 		case MysqlDefs.FIELD_TYPE_LONGLONG:
-			long valueAsLong = getNativeLong(columnIndex + 1);
+			valueAsLong = getNativeLong(columnIndex + 1);
 			
 			if (!f.isUnsigned()) {
 				return (float) valueAsLong;
@@ -3822,7 +3892,17 @@
 		Field f = this.fields[columnIndex];
 
 		switch (f.getMysqlType()) {
-
+		case MysqlDefs.FIELD_TYPE_BIT:
+			long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
+			
+			if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
+					(valueAsLong < Integer.MIN_VALUE
+							|| valueAsLong > Integer.MAX_VALUE)) {
+				throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
+						Types.INTEGER);
+			}
+			
+			return (short)valueAsLong;
 		case MysqlDefs.FIELD_TYPE_TINY:
 			byte tinyintVal = getNativeByte(columnIndex + 1, false);
 			
@@ -3851,7 +3931,7 @@
 				return valueAsInt;
 			}
 			
-			long valueAsLong = (valueAsInt >= 0) ? 
+			valueAsLong = (valueAsInt >= 0) ? 
 					valueAsInt : valueAsInt + 4294967296L; 
 			
 			if (overflowCheck && this.connection.getJdbcCompliantTruncation() &&
@@ -3950,6 +4030,8 @@
 		Field f = this.fields[columnIndex];
 
 		switch (f.getMysqlType()) {
+		case MysqlDefs.FIELD_TYPE_BIT:
+			return getNumericRepresentationOfSQLBitType(columnIndex + 1);
 		case MysqlDefs.FIELD_TYPE_TINY:
 			if (!f.isUnsigned()) {
 				return getNativeByte(columnIndex + 1);
@@ -5056,6 +5138,34 @@
 		return this.serverInfo;
 	}
 
+	private long getNumericRepresentationOfSQLBitType(int columnIndex) throws SQLException {
+		
+		if (this.fields[columnIndex - 1].isSingleBit() || 
+				((byte[])this.thisRow[columnIndex - 1]).length == 1) {
+			return ((byte[])this.thisRow[columnIndex - 1])[0];
+		}
+		
+		
+		byte[] asBytes = (byte[])this.thisRow[columnIndex - 1];
+		
+		int shift = 0;
+		
+		long[] steps = new long[asBytes.length];
+		
+		for (int i = asBytes.length; i >= 0; i--) {
+			steps[i] = (long)(asBytes[i] & 0xff) << 48;
+			shift += 8;
+		}
+		
+		long valueAsLong = 0;
+		
+		for (int i = 0; i < asBytes.length; i++) {
+			valueAsLong |= steps[i];
+		}
+		
+		return valueAsLong;
+	}
+
 	/**
 	 * Get the value of a column in the current row as a Java short.
 	 * 
@@ -5125,6 +5235,19 @@
 							; // ignore, it's not a number
 						}
 
+						if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+							long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
+							
+							if (this.connection.getJdbcCompliantTruncationForReads() &&
+									(valueAsLong < Short.MIN_VALUE
+											|| valueAsLong > Short.MAX_VALUE)) {
+								throwRangeException(String.valueOf(valueAsLong), columnIndex,
+										Types.SMALLINT);
+							}
+							
+							return (short)valueAsLong;
+						}
+						
 						throw SQLError.createSQLException(
 								Messages
 										.getString("ResultSet.Invalid_value_for_getShort()_-____96")
@@ -5164,6 +5287,19 @@
 					; // ignore, it's not a number
 				}
 
+				if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+					long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
+					
+					if (this.connection.getJdbcCompliantTruncationForReads() &&
+							(valueAsLong < Short.MIN_VALUE
+									|| valueAsLong > Short.MAX_VALUE)) {
+						throwRangeException(String.valueOf(valueAsLong), columnIndex,
+								Types.SMALLINT);
+					}
+					
+					return (short)valueAsLong;
+				}
+				
 				throw SQLError.createSQLException(
 						Messages
 								.getString("ResultSet.Invalid_value_for_getShort()_-____96")
@@ -5346,6 +5482,20 @@
 			String stringVal = null;
 			columnIndex--; // JDBC is 1-based, Java is not !?
 
+			if (this.fields[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
+				if (this.fields[columnIndex].isSingleBit()) {
+					byte[] asBytes = (byte[])this.thisRow[columnIndex];
+					
+					if (asBytes.length == 0) {
+						return String.valueOf(convertToZeroWithEmptyCheck());
+					}
+					
+					return String.valueOf(asBytes[0]);
+				}
+				
+				return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex + 1));
+			}
+			
 			String encoding = this.fields[columnIndex].getCharacterSet();
 
 			if ((this.connection != null) && this.connection.getUseUnicode()) {

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	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Statement.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -552,7 +552,12 @@
 	 *                if a database access error occurs
 	 */
 	public boolean execute(String sql) throws SQLException {
-		synchronized (this.connection.getMutex()) {
+		checkClosed();
+		
+
+		Connection locallyScopedConn = this.connection;
+		
+		synchronized (locallyScopedConn.getMutex()) {
 			this.wasCancelled = false;
 	
 			checkNullOrEmptyQuery(sql);
@@ -566,7 +571,7 @@
 			if (firstNonWsChar != 'S') {
 				isSelect = false;
 	
-				if (this.connection.isReadOnly()) {
+				if (locallyScopedConn.isReadOnly()) {
 					throw SQLError.createSQLException(Messages
 							.getString("Statement.27") //$NON-NLS-1$
 							+ Messages.getString("Statement.28"), //$NON-NLS-1$
@@ -576,7 +581,7 @@
 	
 			if (this.doEscapeProcessing) {
 				Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
-						this.connection.serverSupportsConvertFn(), this.connection);
+						locallyScopedConn.serverSupportsConvertFn(), locallyScopedConn);
 	
 				if (escapedSqlResult instanceof String) {
 					sql = (String) escapedSqlResult;
@@ -586,7 +591,7 @@
 			}
 	
 			if (this.results != null) {
-				if (!this.connection.getHoldResultsOpenOverStatementClose()) {
+				if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
 					this.results.realClose(false);
 				}
 			}
@@ -611,31 +616,31 @@
 
 				try {
 					if (this.timeout != 0
-							&& this.connection.versionMeetsMinimum(5, 0, 0)) {
+							&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
 						timeoutTask = new CancelTask();
-						this.connection.getCancelTimer().schedule(timeoutTask, 
+						Connection.getCancelTimer().schedule(timeoutTask, 
 								this.timeout);
 					}
 
 					String oldCatalog = null;
 
-					if (!this.connection.getCatalog().equals(
+					if (!locallyScopedConn.getCatalog().equals(
 							this.currentCatalog)) {
-						oldCatalog = this.connection.getCatalog();
-						this.connection.setCatalog(this.currentCatalog);
+						oldCatalog = locallyScopedConn.getCatalog();
+						locallyScopedConn.setCatalog(this.currentCatalog);
 					}
 
 					//
 					// Check if we have cached metadata for this query...
 					//
-					if (this.connection.getCacheResultSetMetadata()) {
+					if (locallyScopedConn.getCacheResultSetMetadata()) {
 						cachedMetaData = getCachedMetaData(sql);
 					}
 
 					//
 					// Only apply max_rows to selects
 					//
-					if (this.connection.useMaxRows()) {
+					if (locallyScopedConn.useMaxRows()) {
 						int rowLimit = -1;
 
 						if (isSelect) {
@@ -643,7 +648,7 @@
 								rowLimit = this.maxRows;
 							} else {
 								if (this.maxRows <= 0) {
-									this.connection
+									locallyScopedConn
 											.execSQL(
 													this,
 													"SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, //$NON-NLS-1$
@@ -653,7 +658,7 @@
 													false, 
 													this.currentCatalog, true); //$NON-NLS-1$
 								} else {
-									this.connection
+									locallyScopedConn
 											.execSQL(
 													this,
 													"SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, //$NON-NLS-1$
@@ -666,7 +671,7 @@
 								}
 							}
 						} else {
-							this.connection
+							locallyScopedConn
 									.execSQL(
 											this,
 											"SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$
@@ -677,12 +682,12 @@
 						}
 
 						// Finally, execute the query
-						rs = this.connection.execSQL(this, sql, rowLimit, null,
+						rs = locallyScopedConn.execSQL(this, sql, rowLimit, null,
 								this.resultSetType, this.resultSetConcurrency,
 								createStreamingResultSet(), 
 								this.currentCatalog, (cachedMetaData == null));
 					} else {
-						rs = this.connection.execSQL(this, sql, -1, null,
+						rs = locallyScopedConn.execSQL(this, sql, -1, null,
 								this.resultSetType, this.resultSetConcurrency,
 								createStreamingResultSet(), 
 								this.currentCatalog, (cachedMetaData == null));
@@ -694,7 +699,7 @@
 					}
 					
 					if (oldCatalog != null) {
-						this.connection.setCatalog(oldCatalog);
+						locallyScopedConn.setCatalog(oldCatalog);
 					}
 
 					if (this.wasCancelled) {
@@ -737,21 +742,25 @@
 	 */
 	public boolean execute(String sql, int returnGeneratedKeys)
 			throws SQLException {
+		
+		
 		if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) {
 			checkClosed();
-
-			synchronized (this.connection.getMutex()) {
+			
+			Connection locallyScopedConn = this.connection;
+			
+			synchronized (locallyScopedConn.getMutex()) {
 				// If this is a 'REPLACE' query, we need to be able to parse
 				// the 'info' message returned from the server to determine
 				// the actual number of keys generated.
 				boolean readInfoMsgState = this.connection
 						.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 
 				try {
 					return execute(sql);
 				} finally {
-					this.connection.setReadInfoMsgEnabled(readInfoMsgState);
+					locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
 				}
 			}
 		}
@@ -766,19 +775,21 @@
 			throws SQLException {
 		if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) {
 			checkClosed();
-
-			synchronized (this.connection.getMutex()) {
+			
+			Connection locallyScopedConn = this.connection;
+			
+			synchronized (locallyScopedConn.getMutex()) {
 				// If this is a 'REPLACE' query, we need to be able to parse
 				// the 'info' message returned from the server to determine
 				// the actual number of keys generated.
-				boolean readInfoMsgState = this.connection
+				boolean readInfoMsgState = locallyScopedConn
 						.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 
 				try {
 					return execute(sql);
 				} finally {
-					this.connection.setReadInfoMsgEnabled(readInfoMsgState);
+					locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
 				}
 			}
 		}
@@ -794,18 +805,20 @@
 		if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) {
 			checkClosed();
 
-			synchronized (this.connection.getMutex()) {
+			Connection locallyScopedConn = this.connection;
+			
+			synchronized (locallyScopedConn.getMutex()) {
 				// If this is a 'REPLACE' query, we need to be able to parse
 				// the 'info' message returned from the server to determine
 				// the actual number of keys generated.
 				boolean readInfoMsgState = this.connection
 						.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 
 				try {
 					return execute(sql);
 				} finally {
-					this.connection.setReadInfoMsgEnabled(readInfoMsgState);
+					locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
 				}
 			}
 		}
@@ -828,7 +841,11 @@
 	 *             DOCUMENT ME!
 	 */
 	public synchronized int[] executeBatch() throws SQLException {
-		if (this.connection.isReadOnly()) {
+		checkClosed();
+		
+		Connection locallyScopedConn = this.connection;
+		
+		if (locallyScopedConn.isReadOnly()) {
 			throw SQLError.createSQLException(Messages
 					.getString("Statement.34") //$NON-NLS-1$
 					+ Messages.getString("Statement.35"), //$NON-NLS-1$
@@ -836,12 +853,12 @@
 		}
 
 		if (this.results != null) {
-			if (!this.connection.getHoldResultsOpenOverStatementClose()) {
+			if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
 				this.results.realClose(false);
 			}
 		}
 
-		synchronized (this.connection.getMutex()) {
+		synchronized (locallyScopedConn.getMutex()) {
 			try {
 				this.retrieveGeneratedKeys = true;
 				
@@ -852,11 +869,11 @@
 
 					this.batchedGeneratedKeys = new ArrayList(this.batchedArgs.size());
 					
-					boolean multiQueriesEnabled = this.connection.getAllowMultiQueries();
+					boolean multiQueriesEnabled = locallyScopedConn.getAllowMultiQueries();
 					
-					if (this.connection.versionMeetsMinimum(4, 1, 1) && 
+					if (locallyScopedConn.versionMeetsMinimum(4, 1, 1) && 
 							(multiQueriesEnabled || 
-							(this.connection.getRewriteBatchedStatements() && 
+							(locallyScopedConn.getRewriteBatchedStatements() && 
 									nbrCommands > 4))) {
 						return executeBatchUsingMultiQueries(multiQueriesEnabled, nbrCommands);
 					}
@@ -879,7 +896,7 @@
 						} catch (SQLException ex) {
 							updateCounts[commandIndex] = EXECUTE_FAILED;
 
-							if (this.connection.getContinueBatchOnError()) {
+							if (locallyScopedConn.getContinueBatchOnError()) {
 								sqlEx = ex;
 							} else {
 								int[] newUpdateCounts = new int[commandIndex];
@@ -920,8 +937,10 @@
 	private int[] executeBatchUsingMultiQueries(boolean multiQueriesEnabled,
 			int nbrCommands) throws SQLException {
 
+		Connection locallyScopedConn = this.connection;
+		
 		if (!multiQueriesEnabled) {
-			this.connection.getIO().enableMultiQueries();
+			locallyScopedConn.getIO().enableMultiQueries();
 		}
 
 		try {
@@ -935,13 +954,13 @@
 
 			StringBuffer queryBuf = new StringBuffer();
 
-			java.sql.Statement batchStmt = this.connection.createStatement();
+			java.sql.Statement batchStmt = locallyScopedConn.createStatement();
 
 			int counter = 0;
 
 			int numberOfBytesPerChar = 1;
 
-			String connectionEncoding = this.connection.getEncoding();
+			String connectionEncoding = locallyScopedConn.getEncoding();
 
 			if (StringUtils.startsWithIgnoreCase(connectionEncoding, "utf")) {
 				numberOfBytesPerChar = 3;
@@ -1009,7 +1028,7 @@
 			return (updateCounts != null) ? updateCounts : new int[0];
 		} finally {
 			if (!multiQueriesEnabled) {
-				this.connection.getIO().disableMultiQueries();
+				locallyScopedConn.getIO().disableMultiQueries();
 			}
 		}
 	}
@@ -1029,7 +1048,9 @@
 			throws SQLException {
 		checkClosed();
 		
-		synchronized (this.connection.getMutex()) {
+		Connection locallyScopedConn = this.connection;
+		
+		synchronized (locallyScopedConn.getMutex()) {
 			this.wasCancelled = false;
 	
 			checkNullOrEmptyQuery(sql);
@@ -1038,7 +1059,7 @@
 	
 			if (this.doEscapeProcessing) {
 				Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
-						this.connection.serverSupportsConvertFn(), this.connection);
+						locallyScopedConn.serverSupportsConvertFn(), this.connection);
 	
 				if (escapedSqlResult instanceof String) {
 					sql = (String) escapedSqlResult;
@@ -1052,7 +1073,7 @@
 			checkForDml(sql, firstStatementChar);
 	
 			if (this.results != null) {
-				if (!this.connection.getHoldResultsOpenOverStatementClose()) {
+				if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
 					this.results.realClose(false);
 				}
 			}
@@ -1076,40 +1097,40 @@
 
 			try {
 				if (this.timeout != 0
-						&& this.connection.versionMeetsMinimum(5, 0, 0)) {
+						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
 					timeoutTask = new CancelTask();
-					this.connection.getCancelTimer().schedule(timeoutTask, 
+					Connection.getCancelTimer().schedule(timeoutTask, 
 							this.timeout);
 				}
 
 				String oldCatalog = null;
 
-				if (!this.connection.getCatalog().equals(this.currentCatalog)) {
-					oldCatalog = this.connection.getCatalog();
-					this.connection.setCatalog(this.currentCatalog);
+				if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
+					oldCatalog = locallyScopedConn.getCatalog();
+					locallyScopedConn.setCatalog(this.currentCatalog);
 				}
 
 				//
 				// Check if we have cached metadata for this query...
 				//
-				if (this.connection.getCacheResultSetMetadata()) {
+				if (locallyScopedConn.getCacheResultSetMetadata()) {
 					cachedMetaData = getCachedMetaData(sql);
 				}
 
-				if (this.connection.useMaxRows()) {
+				if (locallyScopedConn.useMaxRows()) {
 					// We need to execute this all together
 					// So synchronize on the Connection's mutex (because
 					// even queries going through there synchronize
 					// on the connection
 					if (StringUtils.indexOfIgnoreCase(sql, "LIMIT") != -1) { //$NON-NLS-1$
-						this.results = this.connection.execSQL(this, sql,
+						this.results = locallyScopedConn.execSQL(this, sql,
 								this.maxRows, null, this.resultSetType,
 								this.resultSetConcurrency,
 								createStreamingResultSet(),
 								this.currentCatalog, (cachedMetaData == null));
 					} else {
 						if (this.maxRows <= 0) {
-							this.connection
+							locallyScopedConn
 									.execSQL(
 											this,
 											"SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, null, //$NON-NLS-1$
@@ -1118,7 +1139,7 @@
 											false, this.currentCatalog,
 											true); //$NON-NLS-1$
 						} else {
-							this.connection
+							locallyScopedConn
 									.execSQL(
 											this,
 											"SET OPTION SQL_SELECT_LIMIT=" + this.maxRows, -1, //$NON-NLS-1$
@@ -1129,18 +1150,18 @@
 											true); //$NON-NLS-1$
 						}
 
-						this.results = this.connection.execSQL(this, sql, -1,
+						this.results = locallyScopedConn.execSQL(this, sql, -1,
 								null, this.resultSetType,
 								this.resultSetConcurrency,
 								createStreamingResultSet(),
 								this.currentCatalog, (cachedMetaData == null));
 
 						if (oldCatalog != null) {
-							this.connection.setCatalog(oldCatalog);
+							locallyScopedConn.setCatalog(oldCatalog);
 						}
 					}
 				} else {
-					this.results = this.connection.execSQL(this, sql, -1, null,
+					this.results = locallyScopedConn.execSQL(this, sql, -1, null,
 							this.resultSetType, this.resultSetConcurrency,
 							createStreamingResultSet(),
 							this.currentCatalog, (cachedMetaData == null));
@@ -1152,7 +1173,7 @@
 				}
 				
 				if (oldCatalog != null) {
-					this.connection.setCatalog(oldCatalog);
+					locallyScopedConn.setCatalog(oldCatalog);
 				}
 
 				if (this.wasCancelled) {
@@ -1213,11 +1234,13 @@
 			throws SQLException {
 		checkClosed();
 		
+		Connection locallyScopedConn = this.connection;
+		
 		char firstStatementChar = StringUtils.firstNonWsCharUc(sql);
 
 		ResultSet rs = null;
 
-		synchronized (this.connection.getMutex()) {
+		synchronized (locallyScopedConn.getMutex()) {
 			this.wasCancelled = false;
 	
 			checkNullOrEmptyQuery(sql);
@@ -1233,7 +1256,7 @@
 				}
 			}
 			
-			if (this.connection.isReadOnly()) {
+			if (locallyScopedConn.isReadOnly()) {
 				throw SQLError.createSQLException(Messages
 						.getString("Statement.42") //$NON-NLS-1$
 						+ Messages.getString("Statement.43"), //$NON-NLS-1$
@@ -1247,7 +1270,7 @@
 			}
 	
 			if (this.results != null) {
-				if (!this.connection.getHoldResultsOpenOverStatementClose()) {
+				if (!locallyScopedConn.getHoldResultsOpenOverStatementClose()) {
 					this.results.realClose(false);
 				}
 			}
@@ -1260,24 +1283,24 @@
 
 			try {
 				if (this.timeout != 0
-						&& this.connection.versionMeetsMinimum(5, 0, 0)) {
+						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
 					timeoutTask = new CancelTask();
-					this.connection.getCancelTimer().schedule(timeoutTask, 
+					Connection.getCancelTimer().schedule(timeoutTask, 
 							this.timeout);
 				}
 
 				String oldCatalog = null;
 
-				if (!this.connection.getCatalog().equals(this.currentCatalog)) {
-					oldCatalog = this.connection.getCatalog();
-					this.connection.setCatalog(this.currentCatalog);
+				if (!locallyScopedConn.getCatalog().equals(this.currentCatalog)) {
+					oldCatalog = locallyScopedConn.getCatalog();
+					locallyScopedConn.setCatalog(this.currentCatalog);
 				}
 
 				//
 				// Only apply max_rows to selects
 				//
-				if (this.connection.useMaxRows()) {
-					this.connection.execSQL(
+				if (locallyScopedConn.useMaxRows()) {
+					locallyScopedConn.execSQL(
 							this,
 							"SET OPTION SQL_SELECT_LIMIT=DEFAULT", //$NON-NLS-1$
 							-1, null, java.sql.ResultSet.TYPE_FORWARD_ONLY,
@@ -1285,7 +1308,7 @@
 							this.currentCatalog, true);
 				}
 
-				rs = this.connection.execSQL(this, sql, -1, null,
+				rs = locallyScopedConn.execSQL(this, sql, -1, null,
 						java.sql.ResultSet.TYPE_FORWARD_ONLY,
 						java.sql.ResultSet.CONCUR_READ_ONLY, false,
 						this.currentCatalog,
@@ -1298,7 +1321,7 @@
 				}
 
 				if (oldCatalog != null) {
-					this.connection.setCatalog(oldCatalog);
+					locallyScopedConn.setCatalog(oldCatalog);
 				}
 
 				if (this.wasCancelled) {
@@ -1339,18 +1362,20 @@
 		if (returnGeneratedKeys == java.sql.Statement.RETURN_GENERATED_KEYS) {
 			checkClosed();
 
-			synchronized (this.connection.getMutex()) {
+			Connection locallyScopedConn = this.connection;
+			
+			synchronized (locallyScopedConn.getMutex()) {
 				// If this is a 'REPLACE' query, we need to be able to parse
 				// the 'info' message returned from the server to determine
 				// the actual number of keys generated.
-				boolean readInfoMsgState = this.connection
+				boolean readInfoMsgState = locallyScopedConn
 						.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 
 				try {
 					return executeUpdate(sql);
 				} finally {
-					this.connection.setReadInfoMsgEnabled(readInfoMsgState);
+					locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
 				}
 			}
 		}
@@ -1365,19 +1390,21 @@
 			throws SQLException {
 		if ((generatedKeyIndices != null) && (generatedKeyIndices.length > 0)) {
 			checkClosed();
-
-			synchronized (this.connection.getMutex()) {
+			
+			Connection locallyScopedConn = this.connection;
+			
+			synchronized (locallyScopedConn.getMutex()) {
 				// If this is a 'REPLACE' query, we need to be able to parse
 				// the 'info' message returned from the server to determine
 				// the actual number of keys generated.
-				boolean readInfoMsgState = this.connection
+				boolean readInfoMsgState = locallyScopedConn
 						.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 
 				try {
 					return executeUpdate(sql);
 				} finally {
-					this.connection.setReadInfoMsgEnabled(readInfoMsgState);
+					locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
 				}
 			}
 		}
@@ -1386,14 +1413,6 @@
 	}
 
 	/**
-	 * Required by JDBC spec
-	 */
-	/*
-	 * protected void finalize() throws Throwable { if (!this.isClosed) {
-	 * realClose(false); } }
-	 */
-
-	/**
 	 * @see Statement#executeUpdate(String, String[])
 	 */
 	public int executeUpdate(String sql, String[] generatedKeyNames)
@@ -1401,18 +1420,20 @@
 		if ((generatedKeyNames != null) && (generatedKeyNames.length > 0)) {
 			checkClosed();
 
-			synchronized (this.connection.getMutex()) {
+			Connection locallyScopedConn = this.connection;
+			
+			synchronized (locallyScopedConn.getMutex()) {
 				// If this is a 'REPLACE' query, we need to be able to parse
 				// the 'info' message returned from the server to determine
 				// the actual number of keys generated.
 				boolean readInfoMsgState = this.connection
 						.isReadInfoMsgEnabled();
-				this.connection.setReadInfoMsgEnabled(true);
+				locallyScopedConn.setReadInfoMsgEnabled(true);
 
 				try {
 					return executeUpdate(sql);
 				} finally {
-					this.connection.setReadInfoMsgEnabled(readInfoMsgState);
+					locallyScopedConn.setReadInfoMsgEnabled(readInfoMsgState);
 				}
 			}
 		}

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-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -782,6 +782,16 @@
 		}
 	}
 
+	public boolean isSameResource(Connection c) {
+		if (c instanceof ConnectionWrapper) {
+			return this.mc.isSameResource(((ConnectionWrapper)c).mc);
+		} else if (c instanceof com.mysql.jdbc.Connection) {
+			return this.mc.isSameResource((com.mysql.jdbc.Connection)c);
+		}
+		
+		return false;
+	}
+	
 	protected void close(boolean fireClosedEvent) throws SQLException {
 		synchronized (this.mpc) {
 			if (this.closed) {

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlPooledConnection.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -132,7 +132,7 @@
 					"Physical Connection doesn't exist");
 			callListener(CONNECTION_ERROR_EVENT, sqlException);
 
-			return null;
+			throw sqlException;
 		}
 
 		try {
@@ -149,7 +149,7 @@
 		} catch (SQLException sqlException) {
 			callListener(CONNECTION_ERROR_EVENT, sqlException);
 
-			return null;
+			throw sqlException;
 		}
 
 		return this.logicalHandle;

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-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -164,7 +164,12 @@
 	 */
 	public boolean isSameRM(XAResource xares) throws XAException {
 
-		return (xares == this);
+		if (xares instanceof MysqlXAConnection) {
+			return this.underlyingConnection
+					.isSameResource(((MysqlXAConnection) xares).underlyingConnection);
+		}
+
+		return false;
 	}
 
 	/**

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/profiler/ProfileEventSink.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/profiler/ProfileEventSink.java	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/profiler/ProfileEventSink.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -76,6 +76,10 @@
 		}
 	}
 
+	public static synchronized void removeInstance(Connection conn) {
+		CONNECTIONS_TO_SINKS.remove(conn);
+	}
+
 	private ProfileEventSink(Connection conn) {
 		this.ownerConnection = conn;
 

Modified: branches/branch_5_0/connector-j/src/testsuite/regression/MetaDataRegressionTest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/regression/MetaDataRegressionTest.java	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/testsuite/regression/MetaDataRegressionTest.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -1504,7 +1504,7 @@
 				+ "`");
 		ResultSetMetaData meta = this.rs.getMetaData();
 
-		assertEquals(colName, meta.getColumnName(1));
+		assertEquals(colName, meta.getColumnLabel(1));
 
 	}
 

Modified: branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java	2006-06-07 00:03:01 UTC (rev 5363)
+++ branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java	2006-06-07 14:50:34 UTC (rev 5364)
@@ -3175,6 +3175,63 @@
 		} finally {
 			closeMemberJDBCResources();
 		}
-
 	}
+	
+	public void testBug20029() throws Exception {
+		createTable("testBug20029", ("(field1 int)"));
+		
+		long initialTimeout = 20; // may need to raise this depending on environment
+		                          // we try and do this automatically in this testcase
+		
+		for (int i = 0; i < 10; i++) {
+			final Connection toBeKilledConn = getConnectionWithProps(new Properties());
+			final long timeout = initialTimeout;
+			PreparedStatement toBeKilledPstmt = null;
+			
+			try {
+				toBeKilledPstmt = ((com.mysql.jdbc.Connection)toBeKilledConn).clientPrepareStatement("INSERT INTO testBug20029 VALUES (?)");
+				
+				for (int j = 0; j < 1000; j++) {
+					toBeKilledPstmt.setInt(1, j);
+					toBeKilledPstmt.addBatch();
+				}
+				
+				Thread t = new Thread() {
+					public void run() {
+						try {
+							sleep(timeout);
+							toBeKilledConn.close();
+						} catch (Throwable t) {
+							
+						}
+					}
+				};
+				
+				t.start();
+				
+				try {
+					if (toBeKilledConn.isClosed()) {
+						initialTimeout *= 2;
+						continue;
+					}
+					
+					toBeKilledPstmt.executeBatch();
+					fail("Should've caught a SQLException for the statement being closed here");
+				} catch (BatchUpdateException batchEx) {
+					assertEquals("08003", batchEx.getSQLState());
+					break;
+				}
+				
+				fail("Connection didn't close while in the middle of PreparedStatement.executeBatch()");
+			} finally {
+				if (toBeKilledPstmt != null) {
+					toBeKilledPstmt.close();
+				}
+				
+				if (toBeKilledConn != null) {
+					toBeKilledConn.close();
+				}
+			}
+		}
+	}
 }

Thread
Connector/J commit: r5364 - in branches/branch_5_0/connector-j/src: com/mysql/jdbc com/mysql/jdbc/jdbc2/optional com/mysql/jdbc/profiler testsuite/reg...mmatthews7 Jun