List:Commits« Previous MessageNext Message »
From:mmatthews Date:November 6 2007 7:00pm
Subject:Connector/J commit: r6658 - in trunk: . src/com/mysql/jdbc src/com/mysql/jdbc/jdbc2/optional src/com/mysql/jdbc/profiler src/testsuite/regression src/...
View as plain text  
Added:
   trunk/src/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java
   trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandler.java
   trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandlerFactory.java
Removed:
   trunk/src/com/mysql/jdbc/profiler/ProfileEventSink.java
Modified:
   trunk/
   trunk/CHANGES
   trunk/src/com/mysql/jdbc/Connection.java
   trunk/src/com/mysql/jdbc/ConnectionImpl.java
   trunk/src/com/mysql/jdbc/ConnectionProperties.java
   trunk/src/com/mysql/jdbc/ConnectionPropertiesImpl.java
   trunk/src/com/mysql/jdbc/DatabaseMetaData.java
   trunk/src/com/mysql/jdbc/ExportControlled.java
   trunk/src/com/mysql/jdbc/LocalizedErrorMessages.properties
   trunk/src/com/mysql/jdbc/MysqlIO.java
   trunk/src/com/mysql/jdbc/PreparedStatement.java
   trunk/src/com/mysql/jdbc/ResultSetImpl.java
   trunk/src/com/mysql/jdbc/ResultSetInternalMethods.java
   trunk/src/com/mysql/jdbc/RowDataDynamic.java
   trunk/src/com/mysql/jdbc/ServerPreparedStatement.java
   trunk/src/com/mysql/jdbc/StatementImpl.java
   trunk/src/com/mysql/jdbc/UpdatableResultSet.java
   trunk/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
   trunk/src/testsuite/regression/CallableStatementRegressionTest.java
   trunk/src/testsuite/regression/StatementRegressionTest.java
   trunk/src/testsuite/simple/ConnectionTest.java
Log:
Merged revisions 6585-6586,6593-6597,6599-6602,6605,6607-6609,6612,6614-6617,6619-6620,6623-6627,6632,6636-6638,6641,6649-6657 via svnmerge from 
svn+ssh://mmatthews@stripped/connectors-svnroot/connector-j/branches/branch_5_1

.......
  r6650 | mmatthews | 2007-10-23 14:35:33 -0500 (Tue, 23 Oct 2007) | 1 line
  
  Add some .svn-ignores.
.......
  r6651 | mmatthews | 2007-10-23 18:55:58 -0500 (Tue, 23 Oct 2007) | 1 line
  
  Made profiler event handling extensible via the "profilerEventHandler" connection property.
.......
  r6652 | mmatthews | 2007-10-24 16:13:43 -0500 (Wed, 24 Oct 2007) | 2 lines
  
  Fixed Bug#31823 - CallableStatement.setNull() on a stored function would 
  
        throw an ArrayIndexOutOfBounds when setting the last parameter to null when calling setNull().
.......
  r6653 | mmatthews | 2007-10-29 13:08:17 -0500 (Mon, 29 Oct 2007) | 6 lines
  
  Added SSL-related configuration property "verifyServerCertificate". If set to "false", the driver won't verify 
        the server's certificate when "useSSL" is set to "true".
        
        When using this feature, the keystore parameters should be specified by the 
        "clientCertificateKeyStore*" properties, rather than system properties, as the JSSE doesn't
        make it straightforward to have a non-verifying trust store and the "default" key store.
.......
  r6654 | mmatthews | 2007-10-29 13:15:35 -0500 (Mon, 29 Oct 2007) | 1 line
  
  Use iterated catalog, not the user-specified one.
.......
  r6655 | mmatthews | 2007-10-31 22:34:31 -0500 (Wed, 31 Oct 2007) | 1 line
  
  Pulled up batch rewriting from 5.0.
.......
  r6656 | mmatthews | 2007-11-01 17:01:56 -0500 (Thu, 01 Nov 2007) | 1 line
  
  Use a locally-scoped connection reference after checking for it being closed.
.......
  r6657 | mmatthews | 2007-11-01 17:54:39 -0500 (Thu, 01 Nov 2007) | 3 lines
  
      - Fixed ResultSetMetadata.getColumnName() for result sets returned from
  
        Statement.getGeneratedKeys() - it was returning null instead of
  
        "GENERATED_KEY" as in 5.0.x.
.......



Property changes on: trunk
___________________________________________________________________
Name: svnmerge-integrated
   - /branches/branch_5_0:1-6625 /branches/branch_5_1:1-6582,6584-6648
   + /branches/branch_5_0:1-6625 /branches/branch_5_1:1-6582,6584-6657
Name: svn:ignore
   + build

dist


Modified: trunk/CHANGES
===================================================================
--- trunk/CHANGES	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/CHANGES	2007-11-06 19:00:06 UTC (rev 6658)
@@ -19,6 +19,23 @@
       warning counts and status if talking to a 4.1 or newer server
       (fixes a hang when reading data from 4.0 servers).
       
+    - Made profiler event handling extensible via the "profilerEventHandler"
+      connection property.
+      
+    - Fixed Bug#31823 - CallableStatement.setNull() on a stored function would 
+      throw an ArrayIndexOutOfBounds when setting the last parameter to null when calling setNull().
+
+    - Added SSL-related configuration property "verifyServerCertificate". If set to "false", the driver won't verify 
+      the server's certificate when "useSSL" is set to "true".
+      
+      When using this feature, the keystore parameters should be specified by the 
+      "clientCertificateKeyStore*" properties, rather than system properties, as the JSSE doesn't
+      make it straightforward to have a non-verifying trust store and the "default" key store.
+      
+    - Fixed ResultSetMetadata.getColumnName() for result sets returned from
+      Statement.getGeneratedKeys() - it was returning null instead of
+      "GENERATED_KEY" as in 5.0.x.
+      
 10-09-07 - Version 5.1.5
 
     - Released instead of 5.1.4 to pickup patch for BUG#31053

Modified: trunk/src/com/mysql/jdbc/Connection.java
===================================================================
--- trunk/src/com/mysql/jdbc/Connection.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/Connection.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -360,4 +360,5 @@
 	
 	public abstract boolean isAbonormallyLongQuery(long millisOrNanos);
 
+	public abstract void initializeExtension(Extension ex) throws SQLException;
 }

Modified: trunk/src/com/mysql/jdbc/ConnectionImpl.java
===================================================================
--- trunk/src/com/mysql/jdbc/ConnectionImpl.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ConnectionImpl.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -53,7 +53,8 @@
 import com.mysql.jdbc.log.Log;
 import com.mysql.jdbc.log.LogFactory;
 import com.mysql.jdbc.log.NullLogger;
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandler;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 import com.mysql.jdbc.util.LRUCache;
 
@@ -387,7 +388,7 @@
 	private TimeZone defaultTimeZone;
 
 	/** The event sink to use for profiling */
-	private ProfileEventSink eventSink;
+	private ProfilerEventHandler eventSink;
 
 	private boolean executingFailoverReconnect = false;
 
@@ -3253,7 +3254,7 @@
 		this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME);
 
 		if (getProfileSql() || getUseUsageAdvisor()) {
-			this.eventSink = ProfileEventSink.getInstance(this);
+			this.eventSink = ProfilerEventHandlerFactory.getInstance(this);
 		}
 
 		if (getCachePreparedStatements()) {
@@ -4234,7 +4235,7 @@
 		} finally {
 			this.openStatements = null;
 			this.io = null;
-			ProfileEventSink.removeInstance(this);
+			ProfilerEventHandlerFactory.removeInstance(this);
 			this.isClosed = true;
 		}
 
@@ -5440,4 +5441,8 @@
 		
 		return millisOrNanos > (this.queryTimeMean + 5 * stddev);
 	}
+
+	public void initializeExtension(Extension ex) throws SQLException {
+		ex.init(this, this.props);
+	}
 }

Modified: trunk/src/com/mysql/jdbc/ConnectionProperties.java
===================================================================
--- trunk/src/com/mysql/jdbc/ConnectionProperties.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ConnectionProperties.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -1574,4 +1574,12 @@
 	public abstract String getConnectionLifecycleInterceptors();
 
 	public abstract void setConnectionLifecycleInterceptors(String interceptors);
+	
+	public abstract String getProfilerEventHandler();
+
+	public abstract  void setProfilerEventHandler(String handler);
+	
+	public boolean getVerifyServerCertificate();
+
+	public void setVerifyServerCertificate(boolean flag);
 }

Modified: trunk/src/com/mysql/jdbc/ConnectionPropertiesImpl.java
===================================================================
--- trunk/src/com/mysql/jdbc/ConnectionPropertiesImpl.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ConnectionPropertiesImpl.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -1169,6 +1169,12 @@
 				"3.1.12", //$NON-NLS-1$
 				MISC_CATEGORY, Integer.MIN_VALUE);
 	
+	private StringConnectionProperty profilerEventHandler = new StringConnectionProperty(
+			"profilerEventHandler",
+			"com.mysql.jdbc.profiler.LoggingProfilerEventHandler",
+			Messages.getString("ConnectionProperties.profilerEventHandler"),
+			"5.1.6", DEBUGING_PROFILING_CATEGORY, Integer.MIN_VALUE); //$NON-NLS-1$
+			
 	private StringConnectionProperty profileSql = new StringConnectionProperty(
 			"profileSql", //$NON-NLS-1$
 			null,
@@ -1591,32 +1597,38 @@
 	private StringConnectionProperty clientCertificateKeyStoreUrl = new StringConnectionProperty(
 			"clientCertificateKeyStoreUrl", null, //$NON-NLS-1$
 			Messages.getString("ConnectionProperties.clientCertificateKeyStoreUrl"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$
-			SECURITY_CATEGORY, Integer.MAX_VALUE);
+			SECURITY_CATEGORY, 5);
 	
 	private StringConnectionProperty trustCertificateKeyStoreUrl = new StringConnectionProperty(
 			"trustCertificateKeyStoreUrl", null, //$NON-NLS-1$
 			Messages.getString("ConnectionProperties.trustCertificateKeyStoreUrl"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$
-			SECURITY_CATEGORY, Integer.MAX_VALUE);
+			SECURITY_CATEGORY, 8);
 	
 	private StringConnectionProperty clientCertificateKeyStoreType = new StringConnectionProperty(
 			"clientCertificateKeyStoreType", null, //$NON-NLS-1$
 			Messages.getString("ConnectionProperties.clientCertificateKeyStoreType"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$
-			SECURITY_CATEGORY, Integer.MAX_VALUE);
+			SECURITY_CATEGORY, 6);
 	
 	private StringConnectionProperty clientCertificateKeyStorePassword = new StringConnectionProperty(
 			"clientCertificateKeyStorePassword", null, //$NON-NLS-1$
 			Messages.getString("ConnectionProperties.clientCertificateKeyStorePassword"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$
-			SECURITY_CATEGORY, Integer.MAX_VALUE);
+			SECURITY_CATEGORY, 7);
 	
 	private StringConnectionProperty trustCertificateKeyStoreType = new StringConnectionProperty(
 			"trustCertificateKeyStoreType", null, //$NON-NLS-1$
 			Messages.getString("ConnectionProperties.trustCertificateKeyStoreType"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$
-			SECURITY_CATEGORY, Integer.MAX_VALUE);
+			SECURITY_CATEGORY, 9);
 	
 	private StringConnectionProperty trustCertificateKeyStorePassword = new StringConnectionProperty(
 			"trustCertificateKeyStorePassword", null, //$NON-NLS-1$
 			Messages.getString("ConnectionProperties.trustCertificateKeyStorePassword"), "5.1.0", //$NON-NLS-1$ //$NON-NLS-2$
-			SECURITY_CATEGORY, Integer.MAX_VALUE);
+			SECURITY_CATEGORY, 10);
+
+	private BooleanConnectionProperty verifyServerCertificate = new BooleanConnectionProperty(
+			"verifyServerCertificate",
+			true,
+			Messages.getString("ConnectionProperties.verifyServerCertificate"),
+			"5.1.6", SECURITY_CATEGORY, 4);
 	
 	protected DriverPropertyInfo[] exposeAsDriverPropertyInfoInternal(
 			Properties info, int slotsToReserve) throws SQLException {
@@ -4283,4 +4295,20 @@
 	public void setConnectionLifecycleInterceptors(String interceptors) {
 		this.connectionLifecycleInterceptors.setValue(interceptors);
     }
+
+	public String getProfilerEventHandler() {
+		return this.profilerEventHandler.getValueAsString();
+	}
+
+	public void setProfilerEventHandler(String handler) {
+		this.profilerEventHandler.setValue(handler);
+	}
+
+	public boolean getVerifyServerCertificate() {
+		return this.verifyServerCertificate.getValueAsBoolean();
+	}
+
+	public void setVerifyServerCertificate(boolean flag) {
+		this.verifyServerCertificate.setValue(flag);
+	}
 }

Modified: trunk/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- trunk/src/com/mysql/jdbc/DatabaseMetaData.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/DatabaseMetaData.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -2353,7 +2353,7 @@
 						java.sql.ResultSet tables = null;
 
 						try {
-							tables = getTables(catalog, schemaPattern, "%",
+							tables = getTables((String)catalogStr, schemaPattern, "%",
 									new String[0]);
 
 							while (tables.next()) {
@@ -2377,7 +2377,7 @@
 						java.sql.ResultSet tables = null;
 
 						try {
-							tables = getTables(catalog, schemaPattern,
+							tables = getTables((String)catalogStr, schemaPattern,
 									tableNamePattern, new String[0]);
 
 							while (tables.next()) {
@@ -2419,7 +2419,7 @@
 							queryBuf.append(quotedId);
 							queryBuf.append(" FROM ");
 							queryBuf.append(quotedId);
-							queryBuf.append(catalogStr.toString());
+							queryBuf.append((String)catalogStr);
 							queryBuf.append(quotedId);
 							queryBuf.append(" LIKE '");
 							queryBuf.append(colPattern);
@@ -2450,7 +2450,7 @@
 								fullColumnQueryBuf.append(" FROM ");
 								fullColumnQueryBuf.append(quotedId);
 								fullColumnQueryBuf
-										.append(catalogStr.toString());
+										.append((String)catalogStr);
 								fullColumnQueryBuf.append(quotedId);
 
 								results = stmt.executeQuery(fullColumnQueryBuf
@@ -2475,7 +2475,7 @@
 
 							while (results.next()) {
 								byte[][] rowVal = new byte[23][];
-								rowVal[0] = s2b(catalog); // TABLE_CAT
+								rowVal[0] = s2b((String)catalogStr); // TABLE_CAT
 								rowVal[1] = null; // TABLE_SCHEM (No schemas
 								// in MySQL)
 

Modified: trunk/src/com/mysql/jdbc/ExportControlled.java
===================================================================
--- trunk/src/com/mysql/jdbc/ExportControlled.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ExportControlled.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -1,5 +1,5 @@
 /*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2007 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 
@@ -33,14 +33,18 @@
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.sql.SQLException;
 
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.TrustManagerFactorySpi;
+import javax.net.ssl.X509TrustManager;
 
 /**
  * Holds functionality that falls under export-control regulations.
@@ -124,8 +128,10 @@
 
 		if (StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)
 				&& StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) {
-			return (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory
-					.getDefault();
+			if (mysqlIO.connection.getVerifyServerCertificate()) {
+				return (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory
+						.getDefault();
+			}
 		}
 
 		TrustManagerFactory tmf = null;
@@ -145,13 +151,15 @@
 
 		if (StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)) {
 			try {
-				KeyStore clientKeyStore = KeyStore
-						.getInstance(clientCertificateKeyStoreType);
-				URL ksURL = new URL(clientCertificateKeyStoreUrl);
-				char[] password = (clientCertificateKeyStorePassword == null) ? new char[0]
-						: clientCertificateKeyStorePassword.toCharArray();
-				clientKeyStore.load(ksURL.openStream(), password);
-				kmf.init(clientKeyStore, password);
+				if (!StringUtils.isNullOrEmpty(clientCertificateKeyStoreType)) {
+					KeyStore clientKeyStore = KeyStore
+							.getInstance(clientCertificateKeyStoreType);
+					URL ksURL = new URL(clientCertificateKeyStoreUrl);
+					char[] password = (clientCertificateKeyStorePassword == null) ? new char[0]
+							: clientCertificateKeyStorePassword.toCharArray();
+					clientKeyStore.load(ksURL.openStream(), password);
+					kmf.init(clientKeyStore, password);
+				}
 			} catch (UnrecoverableKeyException uke) {
 				throw SQLError
 						.createSQLException(
@@ -183,14 +191,16 @@
 		if (StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) {
 
 			try {
-				KeyStore trustKeyStore = KeyStore
-						.getInstance(trustCertificateKeyStoreType);
-				URL ksURL = new URL(trustCertificateKeyStoreUrl);
-
-				char[] password = (trustCertificateKeyStorePassword == null) ? new char[0]
-						: trustCertificateKeyStorePassword.toCharArray();
-				trustKeyStore.load(ksURL.openStream(), password);
-				tmf.init(trustKeyStore);
+				if (!StringUtils.isNullOrEmpty(trustCertificateKeyStoreType)) {
+					KeyStore trustKeyStore = KeyStore
+							.getInstance(trustCertificateKeyStoreType);
+					URL ksURL = new URL(trustCertificateKeyStoreUrl);
+	
+					char[] password = (trustCertificateKeyStorePassword == null) ? new char[0]
+							: trustCertificateKeyStorePassword.toCharArray();
+					trustKeyStore.load(ksURL.openStream(), password);
+					tmf.init(trustKeyStore);
+				}
 			} catch (NoSuchAlgorithmException nsae) {
 				throw SQLError.createSQLException(
 						"Unsupported keystore algorithm [" + nsae.getMessage()
@@ -218,16 +228,32 @@
 
 		try {
 			sslContext = SSLContext.getInstance("TLS");
-			sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+			sslContext.init(StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl) ?  null : kmf.getKeyManagers(), mysqlIO.connection
+					.getVerifyServerCertificate() ? tmf.getTrustManagers()
+					: new X509TrustManager[] { new X509TrustManager() {
+						public void checkClientTrusted(X509Certificate[] chain,
+								String authType) {
+							// return without complaint
+						}
 
+						public void checkServerTrusted(X509Certificate[] chain,
+								String authType) throws CertificateException {
+							// return without complaint
+						}
+
+						public X509Certificate[] getAcceptedIssuers() {
+							return null;
+						}
+					} }, null);
+
 			return sslContext.getSocketFactory();
 		} catch (NoSuchAlgorithmException nsae) {
 			throw SQLError.createSQLException("TLS"
-					+ " is not a valid SSL protocol.", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+					+ " is not a valid SSL protocol.",
+					SQL_STATE_BAD_SSL_PARAMS, 0, false);
 		} catch (KeyManagementException kme) {
 			throw SQLError.createSQLException("KeyManagementException: "
 					+ kme.getMessage(), SQL_STATE_BAD_SSL_PARAMS, 0, false);
 		}
 	}
-
 }
\ No newline at end of file

Modified: trunk/src/com/mysql/jdbc/LocalizedErrorMessages.properties
===================================================================
--- trunk/src/com/mysql/jdbc/LocalizedErrorMessages.properties	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/LocalizedErrorMessages.properties	2007-11-06 19:00:06 UTC (rev 6658)
@@ -516,6 +516,7 @@
 ConnectionProperties.prepStmtCacheSize=If prepared statement caching is enabled, how many prepared statements should be cached?
 ConnectionProperties.prepStmtCacheSqlLimit=If prepared statement caching is enabled, what's the largest SQL the driver will cache the parsing for?
 ConnectionProperties.processEscapeCodesForPrepStmts=Should the driver process escape codes in queries that are prepared?
+ConnectionProperties.profilerEventHandler=Name of a class that implements the interface com.mysql.jdbc.profiler.ProfilerEventHandler that will be used to handle profiling/tracing events.
 ConnectionProperties.profileSqlDeprecated=Deprecated, use 'profileSQL' instead. Trace queries and their execution/fetch times on STDERR (true/false) defaults to 'false'
 ConnectionProperties.profileSQL=Trace queries and their execution/fetch times to the configured logger (true/false) defaults to 'false'
 ConnectionProperties.connectionPropertiesTransform=An implementation of com.mysql.jdbc.ConnectionPropertiesTransform that the driver will use to modify URL properties passed to the driver before attempting a connection
@@ -578,6 +579,7 @@
 ConnectionProperties.useUnbufferedInput=Don't use BufferedInputStream for reading data from the server
 ConnectionProperties.useUnicode=Should the driver use Unicode character encodings when handling strings? Should only be used when the driver can't determine the character set mapping, or you are trying to 'force' the driver to use a character set that MySQL either doesn't natively support (such as UTF-8), true/false, defaults to 'true'
 ConnectionProperties.useUsageAdvisor=Should the driver issue 'usage' warnings advising proper and efficient usage of JDBC and MySQL Connector/J to the log (true/false, defaults to 'false')?
+ConnectionProperties.verifyServerCertificate=If "useSSL" is set to "true", should the driver verify the server's certificate? When using this feature, the keystore parameters should be specified by the "clientCertificateKeyStore*" properties, rather than system properties.
 ConnectionProperties.yearIsDateType=Should the JDBC driver treat the MySQL type "YEAR" as a java.sql.Date, or as a SHORT?
 ConnectionProperties.zeroDateTimeBehavior=What should happen when the driver encounters DATETIME values that are composed entirely of zeroes (used by MySQL to represent invalid dates)? Valid values are \"{0}\", \"{1}\" and \"{2}\".
 ConnectionProperties.useJvmCharsetConverters=Always use the character encoding routines built into the JVM, rather than using lookup tables for single-byte character sets?

Modified: trunk/src/com/mysql/jdbc/MysqlIO.java
===================================================================
--- trunk/src/com/mysql/jdbc/MysqlIO.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/MysqlIO.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -49,7 +49,8 @@
 import java.util.Properties;
 import java.util.zip.Deflater;
 
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandler;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 import com.mysql.jdbc.util.ReadAheadInputStream;
 import com.mysql.jdbc.util.ResultSetUtil;
@@ -2058,7 +2059,7 @@
 	    				new Long(queryEndTime - queryStartTime)}));
 	    		mesgBuf.append(profileQueryToLog);
 
-	    		ProfileEventSink eventSink = ProfileEventSink.getInstance(this.connection);
+	    		ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
 
 	    		eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_SLOW_QUERY,
 	    				"", catalog, this.connection.getId(), //$NON-NLS-1$
@@ -2082,7 +2083,7 @@
 
 	    	if (this.logSlowQueries) {
 
-	    		ProfileEventSink eventSink = ProfileEventSink.getInstance(this.connection);
+	    		ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
 
 	    		if (this.queryBadIndexUsed) {
 	    			eventSink.consumeEvent(new ProfilerEvent(
@@ -2116,7 +2117,7 @@
 	    	if (this.profileSql) {
 	    		fetchEndTime = getCurrentTimeNanosOrMillis();
 
-	    		ProfileEventSink eventSink = ProfileEventSink.getInstance(this.connection);
+	    		ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
 
 	    		eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_QUERY,
 	    				"", catalog, this.connection.getId(), //$NON-NLS-1$

Modified: trunk/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- trunk/src/com/mysql/jdbc/PreparedStatement.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/PreparedStatement.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -3341,7 +3341,7 @@
 	 */
 	public void setNull(int parameterIndex, int sqlType) throws SQLException {
 		setInternal(parameterIndex, "null"); //$NON-NLS-1$
-		this.isNull[parameterIndex - 1] = true;
+		this.isNull[parameterIndex - 1 + getParameterIndexOffset()] = true;
 		
 		this.parameterTypes[parameterIndex - 1 + getParameterIndexOffset()] = Types.NULL;
 	}

Modified: trunk/src/com/mysql/jdbc/ResultSetImpl.java
===================================================================
--- trunk/src/com/mysql/jdbc/ResultSetImpl.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ResultSetImpl.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -26,7 +26,8 @@
 
 import com.mysql.jdbc.PreparedStatement.ParseInfo;
 import com.mysql.jdbc.exceptions.NotYetImplementedException;
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandler;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
 import java.io.ByteArrayInputStream;
@@ -217,7 +218,7 @@
 	/** Are we in the middle of doing updates to the current row? */
 	protected boolean doingUpdates = false;
 
-	protected ProfileEventSink eventSink = null;
+	protected ProfilerEventHandler eventSink = null;
 
 	Calendar fastDateCal = null;
 
@@ -493,7 +494,7 @@
 			this.pointOfOrigin = new Throwable();
 			this.resultId = resultCounter++;
 			this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
-			this.eventSink = ProfileEventSink.getInstance(this.connection);
+			this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
 		}
 
 		if (this.connection.getGatherPerformanceMetrics()) {

Modified: trunk/src/com/mysql/jdbc/ResultSetInternalMethods.java
===================================================================
--- trunk/src/com/mysql/jdbc/ResultSetInternalMethods.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ResultSetInternalMethods.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -28,7 +28,7 @@
 import java.util.Map;
 import java.util.TreeMap;
 
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
 /**

Modified: trunk/src/com/mysql/jdbc/RowDataDynamic.java
===================================================================
--- trunk/src/com/mysql/jdbc/RowDataDynamic.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/RowDataDynamic.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -26,7 +26,8 @@
 
 import java.sql.SQLException;
 
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandler;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
 /**
@@ -199,7 +200,7 @@
 				if (conn.getUseUsageAdvisor()) {
 					if (hadMore) {
 
-						ProfileEventSink eventSink = ProfileEventSink
+						ProfilerEventHandler eventSink = ProfilerEventHandlerFactory
 						.getInstance(conn);
 
 						eventSink

Modified: trunk/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- trunk/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -24,9 +24,10 @@
  */
 package com.mysql.jdbc;
 
+import com.mysql.jdbc.StatementImpl.CancelTask;
 import com.mysql.jdbc.exceptions.MySQLStatementCancelledException;
 import com.mysql.jdbc.exceptions.MySQLTimeoutException;
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
 import java.io.IOException;
@@ -208,6 +209,51 @@
 				}
 			}
 		}
+		
+		long getBoundLength() {
+			if (isNull) {
+				return 0;
+			}
+			
+			if (isLongData) {
+				return bindLength;
+			}
+
+			switch (bufferType) {
+
+			case MysqlDefs.FIELD_TYPE_TINY:
+				return 1;
+			case MysqlDefs.FIELD_TYPE_SHORT:
+				return 2;
+			case MysqlDefs.FIELD_TYPE_LONG:
+				return 4;
+			case MysqlDefs.FIELD_TYPE_LONGLONG:
+				return 8;
+			case MysqlDefs.FIELD_TYPE_FLOAT:
+				return 4;
+			case MysqlDefs.FIELD_TYPE_DOUBLE:
+				return 8;
+			case MysqlDefs.FIELD_TYPE_TIME:
+				return 9;
+			case MysqlDefs.FIELD_TYPE_DATE:
+				return 7;
+			case MysqlDefs.FIELD_TYPE_DATETIME:
+			case MysqlDefs.FIELD_TYPE_TIMESTAMP:
+				return 11;
+			case MysqlDefs.FIELD_TYPE_VAR_STRING:
+			case MysqlDefs.FIELD_TYPE_STRING:
+			case MysqlDefs.FIELD_TYPE_VARCHAR:
+			case MysqlDefs.FIELD_TYPE_DECIMAL:
+			case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
+				if (value instanceof byte[]) {
+					return ((byte[]) value).length;
+				} else {
+					return ((String) value).length();
+				}
+			default: 
+				return 0;
+			}
+		}
 	}
 
 	/* 1 (length) + 2 (year) + 1 (month) + 1 (day) */
@@ -616,11 +662,14 @@
 		this.connection.dumpTestcaseQuery(buf.toString());
 	}
 
-	/**
-	 * @see java.sql.Statement#executeBatch()
-	 */
-	public synchronized int[] executeBatch() throws SQLException {
-		if (this.connection.isReadOnly()) {
+	protected int[] executeBatchSerially(int batchTimeout) throws SQLException {
+		ConnectionImpl locallyScopedConn = this.connection;
+		
+		if (locallyScopedConn == null) {
+			checkClosed();
+		}
+		
+		if (locallyScopedConn.isReadOnly()) {
 			throw SQLError.createSQLException(Messages
 					.getString("ServerPreparedStatement.2") //$NON-NLS-1$
 					+ Messages.getString("ServerPreparedStatement.3"), //$NON-NLS-1$
@@ -629,7 +678,7 @@
 
 		checkClosed();
 
-		synchronized (this.connection.getMutex()) {
+		synchronized (locallyScopedConn.getMutex()) {
 			clearWarnings();
 
 			// Store this for later, we're going to 'swap' them out
@@ -657,77 +706,97 @@
 
 					BindValue[] previousBindValuesForBatch = null;
 
-					for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
-						Object arg = this.batchedArgs.get(commandIndex);
-
-						if (arg instanceof String) {
-							updateCounts[commandIndex] = executeUpdate((String) arg);
-						} else {
-							this.parameterBindings = ((BatchedBindValues) arg).batchedParameterValues;
-
-							try {
-								// We need to check types each time, as
-								// the user might have bound different
-								// types in each addBatch()
-
-								if (previousBindValuesForBatch != null) {
-									for (int j = 0; j < this.parameterBindings.length; j++) {
-										if (this.parameterBindings[j].bufferType != previousBindValuesForBatch[j].bufferType) {
-											this.sendTypesToServer = true;
-
-											break;
+					CancelTask timeoutTask = null;
+					
+					try {
+						if (locallyScopedConn.getEnableQueryTimeouts() &&
+								batchTimeout != 0
+								&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
+							timeoutTask = new CancelTask(this);
+							ConnectionImpl.getCancelTimer().schedule(timeoutTask,
+									batchTimeout);
+						}
+						
+						for (commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
+							Object arg = this.batchedArgs.get(commandIndex);
+	
+							if (arg instanceof String) {
+								updateCounts[commandIndex] = executeUpdate((String) arg);
+							} else {
+								this.parameterBindings = ((BatchedBindValues) arg).batchedParameterValues;
+	
+								try {
+									// We need to check types each time, as
+									// the user might have bound different
+									// types in each addBatch()
+	
+									if (previousBindValuesForBatch != null) {
+										for (int j = 0; j < this.parameterBindings.length; j++) {
+											if (this.parameterBindings[j].bufferType != previousBindValuesForBatch[j].bufferType) {
+												this.sendTypesToServer = true;
+	
+												break;
+											}
 										}
 									}
-								}
-
-								try {
-									updateCounts[commandIndex] = executeUpdate(false, true);
-								} finally {
-									previousBindValuesForBatch = this.parameterBindings;
-								}
-
-								if (this.retrieveGeneratedKeys) {
-									java.sql.ResultSet rs = null;
-
+	
 									try {
-										// we don't want to use our version,
-										// because we've altered the behavior of
-										// ours to support batch updates
-										// (catch-22)
-										// Ideally, what we need here is
-										// super.super.getGeneratedKeys()
-										// but that construct doesn't exist in
-										// Java, so that's why there's
-										// this kludge.
-										rs = getGeneratedKeysInternal();
-
-										while (rs.next()) {
-											this.batchedGeneratedKeys
-													.add(new ByteArrayRow(new byte[][] { rs
-															.getBytes(1) }));
-										}
+										updateCounts[commandIndex] = executeUpdate(false, true);
 									} finally {
-										if (rs != null) {
-											rs.close();
+										previousBindValuesForBatch = this.parameterBindings;
+									}
+	
+									if (this.retrieveGeneratedKeys) {
+										java.sql.ResultSet rs = null;
+	
+										try {
+											// we don't want to use our version,
+											// because we've altered the behavior of
+											// ours to support batch updates
+											// (catch-22)
+											// Ideally, what we need here is
+											// super.super.getGeneratedKeys()
+											// but that construct doesn't exist in
+											// Java, so that's why there's
+											// this kludge.
+											rs = getGeneratedKeysInternal();
+	
+											while (rs.next()) {
+												this.batchedGeneratedKeys
+														.add(new ByteArrayRow(new byte[][] { rs
+																.getBytes(1) }));
+											}
+										} finally {
+											if (rs != null) {
+												rs.close();
+											}
 										}
 									}
+								} catch (SQLException ex) {
+									updateCounts[commandIndex] = EXECUTE_FAILED;
+									
+									if (this.continueBatchOnError && 
+											!(ex instanceof MySQLTimeoutException) && 
+											!(ex instanceof MySQLStatementCancelledException)) {
+										sqlEx = ex;
+									} else {
+										int[] newUpdateCounts = new int[commandIndex];
+										System.arraycopy(updateCounts, 0,
+												newUpdateCounts, 0, commandIndex);
+			
+										throw new java.sql.BatchUpdateException(ex
+												.getMessage(), ex.getSQLState(), ex
+												.getErrorCode(), newUpdateCounts);
+									}
 								}
-							} catch (SQLException ex) {
-								updateCounts[commandIndex] = EXECUTE_FAILED;
-
-								if (this.continueBatchOnError) {
-									sqlEx = ex;
-								} else {
-									int[] newUpdateCounts = new int[commandIndex];
-									System.arraycopy(updateCounts, 0,
-											newUpdateCounts, 0, commandIndex);
-
-									throw new java.sql.BatchUpdateException(ex
-											.getMessage(), ex.getSQLState(), ex
-											.getErrorCode(), newUpdateCounts);
-								}
 							}
 						}
+					} finally {
+						if (timeoutTask != null) {
+							timeoutTask.cancel();
+						}
+						
+						resetCancelledState();
 					}
 
 					if (sqlEx != null) {
@@ -1333,7 +1402,7 @@
 				this.connection.incrementNumberOfPreparedExecutes();
 
 				if (this.profileSQL) {
-					this.eventSink = ProfileEventSink
+					this.eventSink = ProfilerEventHandlerFactory
 							.getInstance(this.connection);
 
 					this.eventSink.consumeEvent(new ProfilerEvent(
@@ -2576,5 +2645,184 @@
 		return serverStatementId;
 	}
 
+	public synchronized boolean canRewriteAsMultivalueInsertStatement() {
+		if (!super.canRewriteAsMultivalueInsertStatement()) {
+			return false;
+		}
+	
+		BindValue[] currentBindValues = null;
+		BindValue[] previousBindValues = null;
+	
+		int nbrCommands = this.batchedArgs.size();
+	
+		// Can't have type changes between sets of bindings for this to work...
+	
+		for (int commandIndex = 0; commandIndex < nbrCommands; commandIndex++) {
+			Object arg = this.batchedArgs.get(commandIndex);
+	
+			if (!(arg instanceof String)) {
+	
+				currentBindValues = ((BatchedBindValues) arg).batchedParameterValues;
+	
+				// We need to check types each time, as
+				// the user might have bound different
+				// types in each addBatch()
+	
+				if (previousBindValues != null) {
+					for (int j = 0; j < this.parameterBindings.length; j++) {
+						if (currentBindValues[j].bufferType != previousBindValues[j].bufferType) {
+							return false;
+						}
+					}
+				}
+			}
+		}
+		
+		return true;
+	}
 
+	/** 
+	 *  Computes the maximum parameter set size, and entire batch size given 
+	 *  the number of arguments in the batch.
+	 */
+	protected long[] computeMaxParameterSetSizeAndBatchSize(int numBatchedArgs) {
+		long sizeOfEntireBatch = 1 + /* com_execute */ + 4 /* stmt id */ + 1 /* flags */ + 4 /* batch count padding */; 
+		long maxSizeOfParameterSet = 0;
+		
+		for (int i = 0; i < numBatchedArgs; i++) {
+			BindValue[] paramArg = ((BatchedBindValues) this.batchedArgs.get(i)).batchedParameterValues;
+	
+			long sizeOfParameterSet = 0;
+			
+			sizeOfParameterSet += (this.parameterCount + 7) / 8; // for isNull
+			
+			sizeOfParameterSet += this.parameterCount * 2; // have to send types
+			
+			for (int j = 0; j < this.parameterBindings.length; j++) {
+				if (!paramArg[j].isNull) {
+	
+					long size = paramArg[j].getBoundLength();
+					
+					if (paramArg[j].isLongData) {
+						if (size != -1) {
+							sizeOfParameterSet += size;
+						}
+					} else {
+						sizeOfParameterSet += size;
+					}
+				}
+			}
+			
+			sizeOfEntireBatch += sizeOfParameterSet;
+			
+			if (sizeOfParameterSet > maxSizeOfParameterSet) {
+				maxSizeOfParameterSet = sizeOfParameterSet;
+			}
+		}	
+		
+		return new long[] {maxSizeOfParameterSet, sizeOfEntireBatch};
+	}
+
+	protected int setOneBatchedParameterSet(
+			java.sql.PreparedStatement batchedStatement, int batchedParamIndex,
+			Object paramSet) throws SQLException {
+		BindValue[] paramArg = ((BatchedBindValues) paramSet).batchedParameterValues;
+	
+		for (int j = 0; j < paramArg.length; j++) {
+			if (paramArg[j].isNull) {
+				batchedStatement.setNull(batchedParamIndex++, Types.NULL);
+			} else {
+				if (paramArg[j].isLongData) {
+					Object value = paramArg[j].value;
+	
+					if (value instanceof InputStream) {
+						batchedStatement.setBinaryStream(batchedParamIndex++,
+								(InputStream) value,
+								(int) paramArg[j].bindLength);
+					} else {
+						batchedStatement.setCharacterStream(
+								batchedParamIndex++, (Reader) value,
+								(int) paramArg[j].bindLength);
+					}
+				} else {
+	
+					switch (paramArg[j].bufferType) {
+	
+					case MysqlDefs.FIELD_TYPE_TINY:
+						batchedStatement.setByte(batchedParamIndex++,
+								paramArg[j].byteBinding);
+						break;
+					case MysqlDefs.FIELD_TYPE_SHORT:
+						batchedStatement.setShort(batchedParamIndex++,
+								paramArg[j].shortBinding);
+						break;
+					case MysqlDefs.FIELD_TYPE_LONG:
+						batchedStatement.setInt(batchedParamIndex++,
+								paramArg[j].intBinding);
+						break;
+					case MysqlDefs.FIELD_TYPE_LONGLONG:
+						batchedStatement.setLong(batchedParamIndex++,
+								paramArg[j].longBinding);
+						break;
+					case MysqlDefs.FIELD_TYPE_FLOAT:
+						batchedStatement.setFloat(batchedParamIndex++,
+								paramArg[j].floatBinding);
+						break;
+					case MysqlDefs.FIELD_TYPE_DOUBLE:
+						batchedStatement.setDouble(batchedParamIndex++,
+								paramArg[j].doubleBinding);
+						break;
+					case MysqlDefs.FIELD_TYPE_TIME:
+						batchedStatement.setTime(batchedParamIndex++,
+								(Time) paramArg[j].value);
+						break;
+					case MysqlDefs.FIELD_TYPE_DATE:
+						batchedStatement.setDate(batchedParamIndex++,
+								(Date) paramArg[j].value);
+						break;
+					case MysqlDefs.FIELD_TYPE_DATETIME:
+					case MysqlDefs.FIELD_TYPE_TIMESTAMP:
+						batchedStatement.setTimestamp(batchedParamIndex++,
+								(Timestamp) paramArg[j].value);
+						break;
+					case MysqlDefs.FIELD_TYPE_VAR_STRING:
+					case MysqlDefs.FIELD_TYPE_STRING:
+					case MysqlDefs.FIELD_TYPE_VARCHAR:
+					case MysqlDefs.FIELD_TYPE_DECIMAL:
+					case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
+						Object value = paramArg[j].value;
+	
+						if (value instanceof byte[]) {
+							batchedStatement.setBytes(batchedParamIndex,
+									(byte[]) value);
+						} else {
+							batchedStatement.setString(batchedParamIndex,
+									(String) value);
+						}
+	
+						BindValue asBound = ((ServerPreparedStatement) batchedStatement)
+								.getBinding(
+										batchedParamIndex + 1 /*
+																 * uses 1-based
+																 * offset
+																 */,
+										false);
+						asBound.bufferType = paramArg[j].bufferType;
+	
+						batchedParamIndex++;
+	
+						break;
+					default:
+						throw new IllegalArgumentException(
+								"Unknown type when re-binding parameter into batched statement for parameter index "
+										+ batchedParamIndex);
+					}
+				}
+			}
+		}
+	
+		return batchedParamIndex;
+	}
+
+
 }

Modified: trunk/src/com/mysql/jdbc/StatementImpl.java
===================================================================
--- trunk/src/com/mysql/jdbc/StatementImpl.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/StatementImpl.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -27,7 +27,8 @@
 import com.mysql.jdbc.exceptions.MySQLStatementCancelledException;
 import com.mysql.jdbc.exceptions.NotYetImplementedException;
 import com.mysql.jdbc.exceptions.MySQLTimeoutException;
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandler;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 import com.mysql.jdbc.util.LRUCache;
 
@@ -170,7 +171,7 @@
 	protected boolean doEscapeProcessing = true;
 
 	/** If we're profiling, where should events go to? */
-	protected ProfileEventSink eventSink = null;
+	protected ProfilerEventHandler eventSink = null;
 
 	/** The number of rows to fetch at a time (currently ignored) */
 	private int fetchSize = 0;
@@ -308,7 +309,7 @@
 			this.pointOfOrigin = new Throwable();
 			this.profileSQL = this.connection.getProfileSql();
 			this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
-			this.eventSink = ProfileEventSink.getInstance(this.connection);
+			this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
 		}
 
 		int maxRowsConn = this.connection.getMaxRows();
@@ -1792,6 +1793,7 @@
 		Field[] fields = new Field[1];
 		fields[0] = new Field("", "GENERATED_KEY", Types.BIGINT, 17); //$NON-NLS-1$ //$NON-NLS-2$
 		fields[0].setConnection(this.connection);
+		fields[0].setUseOldNameMetadata(true);
 
 		ArrayList rowSet = new ArrayList();
 

Modified: trunk/src/com/mysql/jdbc/UpdatableResultSet.java
===================================================================
--- trunk/src/com/mysql/jdbc/UpdatableResultSet.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/UpdatableResultSet.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -24,7 +24,7 @@
  */
 package com.mysql.jdbc;
 
-import com.mysql.jdbc.profiler.ProfileEventSink;
+import com.mysql.jdbc.profiler.ProfilerEventHandlerFactory;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
 import java.io.InputStream;
@@ -1177,7 +1177,7 @@
 		if (this.useUsageAdvisor) {
 			if ((this.deleter == null) && (this.inserter == null)
 					&& (this.refresher == null) && (this.updater == null)) {
-				this.eventSink = ProfileEventSink.getInstance(this.connection);
+				this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
 
 				String message = Messages.getString("UpdatableResultSet.34"); //$NON-NLS-1$
 

Modified: trunk/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
===================================================================
--- trunk/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -32,6 +32,7 @@
 import java.util.TimeZone;
 
 import com.mysql.jdbc.ConnectionImpl;
+import com.mysql.jdbc.Extension;
 import com.mysql.jdbc.MysqlErrorNumbers;
 import com.mysql.jdbc.PreparedStatement;
 import com.mysql.jdbc.SQLError;
@@ -2497,4 +2498,24 @@
 	public boolean useUnbufferedInput() {
 		return this.mc.useUnbufferedInput();
 	}
+
+	public void initializeExtension(Extension ex) throws SQLException {
+		this.mc.initializeExtension(ex);
+	}
+
+	public String getProfilerEventHandler() {
+		return this.mc.getProfilerEventHandler();
+	}
+
+	public void setProfilerEventHandler(String handler) {
+		this.mc.setProfilerEventHandler(handler);
+	}
+
+	public boolean getVerifyServerCertificate() {
+		return this.mc.getVerifyServerCertificate();
+	}
+
+	public void setVerifyServerCertificate(boolean flag) {
+		this.mc.setVerifyServerCertificate(flag);
+	}
 }

Copied: trunk/src/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java (from rev 6657, branches/branch_5_1/src/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java)
===================================================================
--- trunk/src/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java	                        (rev 0)
+++ trunk/src/com/mysql/jdbc/profiler/LoggingProfilerEventHandler.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2007 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.profiler;
+
+import java.sql.SQLException;
+import java.util.Properties;
+
+import com.mysql.jdbc.Connection;
+import com.mysql.jdbc.log.Log;
+
+/**
+ * A profile event handler that just logs to the standard
+ * logging mechanism of the JDBC driver.
+ *
+ */
+public class LoggingProfilerEventHandler implements ProfilerEventHandler {
+	private Log log;
+	
+	public LoggingProfilerEventHandler() {}
+	
+	public void consumeEvent(ProfilerEvent evt) {
+		if (evt.eventType == ProfilerEvent.TYPE_WARN) {
+			this.log.logWarn(evt);
+		} else {
+			this.log.logInfo(evt);
+		}
+	}
+
+	public void destroy() {
+		this.log = null;
+	}
+
+	public void init(Connection conn, Properties props) throws SQLException {
+		this.log = conn.getLog();
+	}
+
+}

Deleted: trunk/src/com/mysql/jdbc/profiler/ProfileEventSink.java
===================================================================
--- trunk/src/com/mysql/jdbc/profiler/ProfileEventSink.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/com/mysql/jdbc/profiler/ProfileEventSink.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -1,91 +0,0 @@
-/*
- Copyright (C) 2002-2007 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.profiler;
-
-import com.mysql.jdbc.Connection;
-import com.mysql.jdbc.log.Log;
-
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author mmatthew
- */
-public class ProfileEventSink {
-
-	private static final Map CONNECTIONS_TO_SINKS = new HashMap();
-
-	private Connection ownerConnection = null;
-
-	private Log log = null;
-
-	/**
-	 * Returns the ProfileEventSink that handles profiler events for the given
-	 * connection.
-	 * 
-	 * @param conn
-	 *            the connection to handle events for
-	 * @return the ProfileEventSink that handles profiler events
-	 */
-	public static synchronized ProfileEventSink getInstance(Connection conn) {
-		ProfileEventSink sink = (ProfileEventSink) CONNECTIONS_TO_SINKS
-				.get(conn);
-
-		if (sink == null) {
-			sink = new ProfileEventSink(conn);
-			CONNECTIONS_TO_SINKS.put(conn, sink);
-		}
-
-		return sink;
-	}
-
-	/**
-	 * Process a profiler event
-	 * 
-	 * @param evt
-	 *            the event to process
-	 */
-	public void consumeEvent(ProfilerEvent evt) {
-		if (evt.eventType == ProfilerEvent.TYPE_WARN) {
-			this.log.logWarn(evt);
-		} else {
-			this.log.logInfo(evt);
-		}
-	}
-
-	public static synchronized void removeInstance(Connection conn) {
-		CONNECTIONS_TO_SINKS.remove(conn);
-	}
-
-	private ProfileEventSink(Connection conn) {
-		this.ownerConnection = conn;
-
-		try {
-			this.log = this.ownerConnection.getLog();
-		} catch (SQLException sqlEx) {
-			throw new RuntimeException("Unable to get logger from connection");
-		}
-	}
-}
\ No newline at end of file

Copied: trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandler.java (from rev 6657, branches/branch_5_1/src/com/mysql/jdbc/profiler/ProfilerEventHandler.java)
===================================================================
--- trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandler.java	                        (rev 0)
+++ trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandler.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -0,0 +1,31 @@
+/*
+ Copyright (C) 2007 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.profiler;
+
+import com.mysql.jdbc.Extension;
+
+public interface ProfilerEventHandler extends Extension {
+	
+	public void consumeEvent(ProfilerEvent evt);
+}

Copied: trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandlerFactory.java (from rev 6657, branches/branch_5_1/src/com/mysql/jdbc/profiler/ProfilerEventHandlerFactory.java)
===================================================================
--- trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandlerFactory.java	                        (rev 0)
+++ trunk/src/com/mysql/jdbc/profiler/ProfilerEventHandlerFactory.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -0,0 +1,88 @@
+/*
+ Copyright (C) 2002-2007 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.profiler;
+
+import com.mysql.jdbc.Connection;
+import com.mysql.jdbc.log.Log;
+import com.mysql.jdbc.Util;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author mmatthew
+ */
+public class ProfilerEventHandlerFactory {
+
+	private static final Map CONNECTIONS_TO_SINKS = new HashMap();
+
+	private Connection ownerConnection = null;
+
+	private Log log = null;
+
+	/**
+	 * Returns the ProfilerEventHandlerFactory that handles profiler events for the given
+	 * connection.
+	 * 
+	 * @param conn
+	 *            the connection to handle events for
+	 * @return the ProfilerEventHandlerFactory that handles profiler events
+	 */
+	public static synchronized ProfilerEventHandler getInstance(Connection conn) throws SQLException {
+		ProfilerEventHandler handler = (ProfilerEventHandler) CONNECTIONS_TO_SINKS
+				.get(conn);
+
+		if (handler == null) {
+			handler = (ProfilerEventHandler)Util.getInstance(conn.getProfilerEventHandler(), new Class[0], new Object[0]);
+			
+			// we do it this way to not require
+			// exposing the connection properties 
+			// for all who utilize it
+			conn.initializeExtension(handler);
+			
+			CONNECTIONS_TO_SINKS.put(conn, handler);
+		}
+
+		return handler;
+	}
+
+	public static synchronized void removeInstance(Connection conn) {
+		ProfilerEventHandler handler = (ProfilerEventHandler) CONNECTIONS_TO_SINKS.remove(conn);
+		
+		if (handler != null) {
+			handler.destroy();
+		}
+	}
+
+	private ProfilerEventHandlerFactory(Connection conn) {
+		this.ownerConnection = conn;
+
+		try {
+			this.log = this.ownerConnection.getLog();
+		} catch (SQLException sqlEx) {
+			throw new RuntimeException("Unable to get logger from connection");
+		}
+	}
+}
\ No newline at end of file

Modified: trunk/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
--- trunk/src/testsuite/regression/CallableStatementRegressionTest.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/testsuite/regression/CallableStatementRegressionTest.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -27,6 +27,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.sql.CallableStatement;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -1243,4 +1245,159 @@
 			}
 		}
 	}
+	
+	/** 
+	 * Tests fix for Bug#31823 - CallableStatement.setNull() on a stored
+	 * function would throw an ArrayIndexOutOfBounds when setting the 
+	 * last parameter to null when calling setNull().
+	 * 
+	 * @throws Exception
+	 */
+	public void testBug31823() throws Exception {
+		if (!versionMeetsMinimum(5, 0)) {
+			return; // no stored functions
+		}
+
+		createTable("testBug31823",
+				"(value_1 BIGINT PRIMARY KEY,value_2 VARCHAR(20))");
+
+		createFunction(
+				"f_testBug31823",
+				"(value_1_v BIGINT,value_2_v VARCHAR(20)) RETURNS BIGINT "
+						+ "DETERMINISTIC MODIFIES SQL DATA BEGIN INSERT INTO testBug31823 VALUES (value_1_v,value_2_v); "
+						+ "RETURN value_1_v; END;");
+
+		// Prepare the function call
+		CallableStatement callable = null;
+
+		try {
+			callable = this.conn.prepareCall("{? = call f_testBug31823(?,?)}");
+
+			callable.registerOutParameter(1, Types.BIGINT);
+
+			// Add row with non-null value
+			callable.setLong(2, 1);
+			callable.setString(3, "Non-null value");
+			callable.executeUpdate();
+			assertEquals(1, callable.getLong(1));
+
+			// Add row with null value
+			callable.setLong(2, 2);
+			callable.setNull(3, Types.VARCHAR);
+			callable.executeUpdate();
+			assertEquals(2, callable.getLong(1));
+
+			Method[] setters = CallableStatement.class.getMethods();
+
+			for (int i = 0; i < setters.length; i++) {
+				if (setters[i].getName().startsWith("set")) {
+					Class[] args = setters[i].getParameterTypes();
+
+					if (args.length == 2 && args[0].equals(Integer.TYPE)) {
+						if (!args[1].isPrimitive()) {
+							try {
+								setters[i].invoke(callable, new Object[] {
+										new Integer(2), null });
+							} catch (InvocationTargetException ive) {
+								if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+									throw ive;
+								}
+							}
+						} else {
+							if (args[1].getName().equals("boolean")) {
+								try {
+									setters[i].invoke(callable, new Object[] {
+											new Integer(2), Boolean.FALSE });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+							}
+
+							if (args[1].getName().equals("byte")) {
+
+								try {
+									setters[i].invoke(callable,
+											new Object[] { new Integer(2),
+													new Byte((byte) 0) });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+
+							}
+
+							if (args[1].getName().equals("double")) {
+
+								try {
+									setters[i].invoke(callable, new Object[] {
+											new Integer(2), new Double(0) });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+
+							}
+
+							if (args[1].getName().equals("float")) {
+
+								try {
+									setters[i].invoke(callable, new Object[] {
+											new Integer(2), new Float(0) });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+
+							}
+
+							if (args[1].getName().equals("int")) {
+
+								try {
+									setters[i].invoke(callable, new Object[] {
+											new Integer(2), new Integer(0) });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+
+							}
+
+							if (args[1].getName().equals("long")) {
+								try {
+									setters[i].invoke(callable, new Object[] {
+											new Integer(2), new Long(0) });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+							}
+
+							if (args[1].getName().equals("short")) {
+								try {
+									setters[i].invoke(callable, new Object[] {
+											new Integer(2),
+											new Short((short) 0) });
+								} catch (InvocationTargetException ive) {
+									if (!(ive.getCause() instanceof com.mysql.jdbc.NotImplemented)) {
+										throw ive;
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		} finally {
+			if (callable != null) {
+				callable.close();
+			}
+		}
+	}
 }
\ No newline at end of file

Modified: trunk/src/testsuite/regression/StatementRegressionTest.java
===================================================================
--- trunk/src/testsuite/regression/StatementRegressionTest.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/testsuite/regression/StatementRegressionTest.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -4120,4 +4120,36 @@
 			closeMemberJDBCResources();
 		}
 	}
+	
+	public void testBustedGGKColumnNames() throws Exception {
+		createTable("testBustedGGKColumnNames",
+				"(field1 int primary key auto_increment)");
+
+		try {
+			this.stmt.executeUpdate(
+					"INSERT INTO testBustedGGKColumnNames VALUES (null)",
+					Statement.RETURN_GENERATED_KEYS);
+			assertEquals("GENERATED_KEY", this.stmt.getGeneratedKeys()
+					.getMetaData().getColumnName(1));
+	
+			this.pstmt = this.conn.prepareStatement(
+					"INSERT INTO testBustedGGKColumnNames VALUES (null)",
+					Statement.RETURN_GENERATED_KEYS);
+			this.pstmt.executeUpdate();
+			assertEquals("GENERATED_KEY", this.pstmt.getGeneratedKeys()
+					.getMetaData().getColumnName(1));
+	
+			if (versionMeetsMinimum(4, 1, 0)) {
+				this.pstmt = ((com.mysql.jdbc.Connection) this.conn)
+						.serverPrepareStatement(
+								"INSERT INTO testBustedGGKColumnNames VALUES (null)",
+								Statement.RETURN_GENERATED_KEYS);
+				this.pstmt.executeUpdate();
+				assertEquals("GENERATED_KEY", this.pstmt.getGeneratedKeys()
+						.getMetaData().getColumnName(1));
+			}
+		} finally {
+			closeMemberJDBCResources();
+		}
+	}
 }

Modified: trunk/src/testsuite/simple/ConnectionTest.java
===================================================================
--- trunk/src/testsuite/simple/ConnectionTest.java	2007-11-01 22:54:39 UTC (rev 6657)
+++ trunk/src/testsuite/simple/ConnectionTest.java	2007-11-06 19:00:06 UTC (rev 6658)
@@ -357,131 +357,131 @@
 
 				/*
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL BE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL VE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL GE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL DE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL IE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL IO')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL ZHE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL ZE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL I')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL KA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL EL')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL EM')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL EN')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL O')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL PE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL ER')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL ES')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL TE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL U')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL EF')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL HA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL TSE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL CHE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL SHA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL SCHA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL HARD SIGN')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL YERU')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL SOFT SIGN')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL E')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL YU')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR SMALL YA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT A')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT BE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT VE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT GE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT DE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT IE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT IO')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT ZHE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT ZE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT I')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT KA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT EL')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT EM')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT EN')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT O')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT PE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT ER')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT ES')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT TE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT U')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT EF')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT HA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT TSE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT CHE')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT SHA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT SCHA')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT HARD SIGN')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT YERU')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT SOFT SIGN')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT E')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT YU')");
 				 * this.stmt.executeUpdate("INSERT INTO t1 (koi8_ru_f,comment)
-				 * VALUES (_koi8r'?+				 * VALUES (_koi8r'?��','CYR CAPIT YA')");
 				 */
 
 				this.stmt
@@ -1598,4 +1598,8 @@
 			}
     	}
 	}
+	
+	public void testNonVerifyServerCert() throws Exception {
+		getConnectionWithProps("useSSL=true,verifyServerCertificate=false,requireSSL=true");
+	}
 }

Thread
Connector/J commit: r6658 - in trunk: . src/com/mysql/jdbc src/com/mysql/jdbc/jdbc2/optional src/com/mysql/jdbc/profiler src/testsuite/regression src/...mmatthews6 Nov