List:Commits« Previous MessageNext Message »
From:mmatthews Date:March 15 2007 8:13pm
Subject:Connector/J commit: r6349 - trunk/connector-j/src/com/mysql/jdbc
View as plain text  
Added:
   trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java
Modified:
   trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
   trunk/connector-j/src/com/mysql/jdbc/Connection.java
   trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
   trunk/connector-j/src/com/mysql/jdbc/JDBC4Connection.java
   trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaData.java
   trunk/connector-j/src/com/mysql/jdbc/JDBC4PreparedStatement.java
   trunk/connector-j/src/com/mysql/jdbc/JDBC4ResultSet.java
   trunk/connector-j/src/com/mysql/jdbc/JDBC4UpdatableResultSet.java
   trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java
   trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
   trunk/connector-j/src/com/mysql/jdbc/ResultSet.java
   trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java
   trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
   trunk/connector-j/src/com/mysql/jdbc/Statement.java
   trunk/connector-j/src/com/mysql/jdbc/Util.java
Log:
Cleaned up dynamic instantiation of JDBC-4 variants of classes, and also improved performance (cache the reflected constructors statically in each class)

enabled our wrapper/unwrapper implementation for JDBC-4.0 for core classes, need real implementation for CPDS and XADS.

Modified: trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -26,6 +26,8 @@
 import java.io.Reader;
 import java.io.UnsupportedEncodingException;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 
 import java.net.URL;
@@ -47,6 +49,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 
 import com.mysql.jdbc.exceptions.NotYetImplementedException;
 
@@ -59,6 +62,37 @@
  */
 public class CallableStatement extends PreparedStatement implements
 		java.sql.CallableStatement {
+	protected final static Constructor JDBC_4_CSTMT_2_ARGS_CTOR;
+	
+	protected final static Constructor JDBC_4_CSTMT_4_ARGS_CTOR;
+	
+	static {
+		if (Util.isJdbc4()) {
+			try {
+				JDBC_4_CSTMT_2_ARGS_CTOR = Class.forName(
+						"com.mysql.jdbc.jdbc4.JDBC4CallableStatement")
+						.getConstructor(
+								new Class[] { com.mysql.jdbc.Connection.class,
+										CallableStatementParamInfo.class });
+				JDBC_4_CSTMT_4_ARGS_CTOR = Class.forName(
+						"com.mysql.jdbc.jdbc4.JDBC4CallableStatement")
+						.getConstructor(
+								new Class[] { com.mysql.jdbc.Connection.class,
+										String.class, String.class,
+										Boolean.TYPE });
+			} catch (SecurityException e) {
+				throw new RuntimeException(e);
+			} catch (NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException(e);
+			}
+		} else {
+			JDBC_4_CSTMT_4_ARGS_CTOR = null;
+			JDBC_4_CSTMT_2_ARGS_CTOR = null;
+		}
+	}
+	
 	protected class CallableStatementParam {
 		int desiredJdbcType;
 
@@ -348,13 +382,53 @@
 			super(paramInfo);
 		}
 		
-		public boolean isWrapperFor(Class arg0) throws SQLException {
-			throw new NotYetImplementedException();
+		/**
+	     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+	     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+	     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+	     * object. If this does not implement the interface and is not a wrapper, return false.
+	     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+	     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+	     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+	     *
+	     * @param interfaces a Class defining an interface.
+	     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+	     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+	     * for an object with the given interface.
+	     * @since 1.6
+	     */
+		public boolean isWrapperFor(Class iface) throws SQLException {
+			checkClosed();
+			
+			// This works for classes that aren't actually wrapping
+			// anything
+			return iface.isInstance(this);
 		}
 
-		public Object unwrap(Class arg0) throws SQLException {
-			throw new NotYetImplementedException();
-		}
+	    /**
+	     * Returns an object that implements the given interface to allow access to non-standard methods,
+	     * or standard methods not exposed by the proxy.
+	     * The result may be either the object found to implement the interface or a proxy for that object.
+	     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+	     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+	     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+	     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+	     *
+	     * @param iface A Class defining an interface that the result must implement.
+	     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+	     * @throws java.sql.SQLException If no object found that implements the interface 
+	     * @since 1.6
+	     */
+		public Object unwrap(Class iface) throws java.sql.SQLException {
+	    	try {
+	    		// This works for classes that aren't actually wrapping
+	    		// anything
+	            return iface.cast(this);
+	        } catch (ClassCastException cce) {
+	            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+	            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+	        }
+	    }
 	}
 
 	private final static int NOT_OUTPUT_PARAMETER_INDICATOR = Integer.MIN_VALUE;
@@ -430,17 +504,15 @@
 	 * classes that are present in JDBC4 method signatures.
 	 */
 
-	protected static CallableStatement getInstance(Connection conn, String sql, String catalog,
-			boolean isFunctionCall) throws SQLException {
+	protected static CallableStatement getInstance(Connection conn, String sql,
+			String catalog, boolean isFunctionCall) throws SQLException {
 		if (!Util.isJdbc4()) {
 			return new CallableStatement(conn, sql, catalog, isFunctionCall);
 		}
 
-		return (CallableStatement) Util.getInstance(
-				"com.mysql.jdbc.jdbc4.JDBC4CallableStatement", new Class[] {
-						com.mysql.jdbc.Connection.class, String.class, String.class,
-						Boolean.TYPE }, new Object[] {
-						conn, sql, catalog, new Boolean(isFunctionCall) });
+		return (CallableStatement) Util.handleNewInstance(
+				JDBC_4_CSTMT_4_ARGS_CTOR, new Object[] { conn, sql, catalog,
+						new Boolean(isFunctionCall) });
 	}
 	
 	/**
@@ -456,10 +528,9 @@
 			return new CallableStatement(conn, paramInfo);
 		}
 
-		return (CallableStatement) Util.getInstance(
-				"com.mysql.jdbc.jdbc4.JDBC4CallableStatement", new Class[] {
-						com.mysql.jdbc.Connection.class, CallableStatementParamInfo.class }, 
-						new Object[] {conn, conn, paramInfo });
+		return (CallableStatement) Util.handleNewInstance(
+				JDBC_4_CSTMT_2_ARGS_CTOR, new Object[] { conn, paramInfo });
+
 	}
 	
 	private int[] placeholderToParameterIndexMap;

Modified: trunk/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Connection.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/Connection.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -29,6 +29,7 @@
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import java.sql.Blob;
@@ -168,7 +169,8 @@
 	private static final Map serverConfigByUrl = new HashMap();
 
 	private static Timer cancelTimer;
-
+	private static final Constructor JDBC_4_CONNECTION_CTOR;
+	
 	static {
 		mapTransIsolationNameToValue = new HashMap(8);
 		mapTransIsolationNameToValue.put("READ-UNCOMMITED", new Integer(
@@ -198,6 +200,23 @@
 		if (!createdNamedTimer) {
 			cancelTimer = new Timer(true);
 		}
+		
+		if (Util.isJdbc4()) {
+			try {
+				JDBC_4_CONNECTION_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4Connection").getConstructor(
+						new Class[] { String.class, Integer.TYPE,
+								Properties.class, String.class, String.class });
+			} catch (SecurityException e) {
+				throw new RuntimeException(e);
+			} catch (NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException(e);
+			}
+		} else {
+			JDBC_4_CONNECTION_CTOR = null;
+		}
 	}
 
 	protected static SQLException appendMessageToException(SQLException sqlEx,
@@ -257,6 +276,7 @@
 		return cancelTimer;
 	}
 
+	
 	/**
 	 * Creates a connection instance -- We need to provide factory-style methods
 	 * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
@@ -272,12 +292,10 @@
 					databaseToConnectTo, url);
 		}
 
-		return (Connection) Util.getInstance(
-				"com.mysql.jdbc.JDBC4Connection", new Class[] {
-						String.class, Integer.TYPE, Properties.class,
-						String.class, String.class }, new Object[] {
-						hostToConnectTo, new Integer(portToConnectTo), info,
-						databaseToConnectTo, url });
+		return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR,
+				new Object[] {
+							hostToConnectTo, new Integer(portToConnectTo), info,
+							databaseToConnectTo, url });
 	}
 
 	private static synchronized int getNextRoundRobinHostIndex(String url,
@@ -1046,7 +1064,7 @@
 		}
 	}
 
-	private void checkClosed() throws SQLException {
+	protected void checkClosed() throws SQLException {
 		if (this.isClosed) {
 			StringBuffer messageBuf = new StringBuffer(
 					"No operations allowed after connection closed.");

Modified: trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -25,6 +25,8 @@
 package com.mysql.jdbc;
 
 import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -472,7 +474,34 @@
 
 	private static final byte[] VIEW_AS_BYTES = "VIEW".getBytes();
 	
+	private static final Constructor JDBC_4_DBMD_SHOW_CTOR;
+	
+	private static final Constructor JDBC_4_DBMD_IS_CTOR;
+	
 	static {
+		if (Util.isJdbc4()) {
+			try {
+				JDBC_4_DBMD_SHOW_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4DatabaseMetaData").getConstructor(
+						new Class[] { com.mysql.jdbc.Connection.class,
+								String.class });
+				JDBC_4_DBMD_IS_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4DatabaseMetaDataUsingInfoSchema")
+						.getConstructor(
+								new Class[] { com.mysql.jdbc.Connection.class,
+										String.class });
+			} catch (SecurityException e) {
+				throw new RuntimeException(e);
+			} catch (NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException(e);
+			}
+		} else {
+			JDBC_4_DBMD_IS_CTOR = null;
+			JDBC_4_DBMD_SHOW_CTOR = null;
+		}
+		
 		// Current as-of MySQL-5.1.16
 		String[] allMySQLKeywords = new String[] { "ACCESSIBLE", "ADD", "ALL",
 				"ALTER", "ANALYZE", "AND", "AS", "ASC", "ASENSITIVE", "BEFORE",
@@ -620,17 +649,13 @@
 
 		if (connToSet != null && connToSet.getUseInformationSchema()
 				&& connToSet.versionMeetsMinimum(5, 0, 7)) {
-			return (DatabaseMetaData) Util
-					.getInstance(
-							"com.mysql.jdbc.JDBC4DatabaseMetaDataUsingInfoSchema",
-							new Class[] { com.mysql.jdbc.Connection.class,
-									String.class }, new Object[] { connToSet,
-									databaseToSet });
+
+			return (DatabaseMetaData) Util.handleNewInstance(
+					JDBC_4_DBMD_IS_CTOR, new Object[] { connToSet,
+							databaseToSet });
 		}
 
-		return (DatabaseMetaData) Util.getInstance(
-				"com.mysql.jdbc.JDBC4DatabaseMetaData", new Class[] {
-						com.mysql.jdbc.Connection.class, String.class },
+		return (DatabaseMetaData) Util.handleNewInstance(JDBC_4_DBMD_SHOW_CTOR,
 				new Object[] { connToSet, databaseToSet });
 	}
 	

Modified: trunk/connector-j/src/com/mysql/jdbc/JDBC4Connection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/JDBC4Connection.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/JDBC4Connection.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -75,14 +75,54 @@
 		throw new NotYetImplementedException();
 	}
 
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+    /**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		checkClosed();
+		
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
-
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+    public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
+    
 	/**
 	 * @see java.sql.Connection#createBlob()
 	 */

Modified: trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaData.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaData.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -131,20 +131,57 @@
 		return true;
 	}
 
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
-
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+    public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
+    
 	public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException {
 		throw new NotYetImplementedException();
 	}
 
 	public boolean providesQueryObjectGenerator() throws SQLException {
-		// TODO Auto-generated method stub
 		return false;
 	}
 

Added: trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/JDBC4DatabaseMetaDataUsingInfoSchema.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -0,0 +1,191 @@
+/*
+ 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;
+
+import java.sql.ResultSet;
+import java.sql.RowIdLifetime;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import com.mysql.jdbc.Connection;
+import com.mysql.jdbc.DatabaseMetaData;
+import com.mysql.jdbc.DatabaseMetaDataUsingInfoSchema;
+import com.mysql.jdbc.Field;
+import com.mysql.jdbc.exceptions.NotYetImplementedException;
+
+public class JDBC4DatabaseMetaDataUsingInfoSchema extends DatabaseMetaDataUsingInfoSchema {
+	public JDBC4DatabaseMetaDataUsingInfoSchema(Connection connToSet, String databaseToSet) {
+		super(connToSet, databaseToSet);
+	}
+
+	public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
+		return false;
+	}
+
+	public ResultSet getClientInfoProperties() throws SQLException {
+		throw new NotYetImplementedException();
+	}
+
+	public ResultSet getFunctionParameters(String catalog, String schemaPattern, String functionNamePattern, String parameterNamePattern) throws SQLException {
+		throw new NotYetImplementedException();
+	}
+
+    /**
+     * Retrieves a description of the  system and user functions available 
+     * in the given catalog.
+     * <P>
+     * Only system and user function descriptions matching the schema and
+     * function name criteria are returned.  They are ordered by
+     * <code>FUNCTION_CAT</code>, <code>FUNCTION_SCHEM</code>,
+     * <code>FUNCTION_NAME</code> and 
+     * <code>SPECIFIC_ NAME</code>.
+     *
+     * <P>Each function description has the the following columns:
+     *  <OL>
+     *	<LI><B>FUNCTION_CAT</B> String => function catalog (may be <code>null</code>)
+     *	<LI><B>FUNCTION_SCHEM</B> String => function schema (may be <code>null</code>)
+     *	<LI><B>FUNCTION_NAME</B> String => function name.  This is the name 
+     * used to invoke the function
+     *	<LI><B>REMARKS</B> String => explanatory comment on the function
+     * <LI><B>FUNCTION_TYPE</B> short => kind of function:
+     *      <UL>
+     *      <LI>functionResultUnknown - Cannot determine if a return value
+     *       or table will be returned
+     *      <LI> functionNoTable- Does not return a table
+     *      <LI> functionReturnsTable - Returns a table
+     *      </UL>
+     *	<LI><B>SPECIFIC_NAME</B> String  => the name which uniquely identifies 
+     *  this function within its schema.  This is a user specified, or DBMS
+     * generated, name that may be different then the <code>FUNCTION_NAME</code> 
+     * for example with overload functions
+     *  </OL>
+     * <p>
+     * A user may not have permission to execute any of the functions that are
+     * returned by <code>getFunctions</code>
+     *
+     * @param catalog a catalog name; must match the catalog name as it
+     *        is stored in the database; "" retrieves those without a catalog;
+     *        <code>null</code> means that the catalog name should not be used to narrow
+     *        the search
+     * @param schemaPattern a schema name pattern; must match the schema name
+     *        as it is stored in the database; "" retrieves those without a schema;
+     *        <code>null</code> means that the schema name should not be used to narrow
+     *        the search
+     * @param functionNamePattern a function name pattern; must match the
+     *        function name as it is stored in the database 
+     * @return <code>ResultSet</code> - each row is a function description 
+     * @exception SQLException if a database access error occurs
+     * @see #getSearchStringEscape 
+     * @since 1.6
+     */
+	public ResultSet getFunctions(String catalog, String schemaPattern,
+			String functionNamePattern) throws SQLException {
+
+		Field[] fields = new Field[6];
+		fields[0] = new Field("", "FUNCTION_CAT", Types.CHAR,
+				MAX_IDENTIFIER_LENGTH);
+		fields[1] = new Field("", "FUNCTION_SCHEM", Types.CHAR,
+				MAX_IDENTIFIER_LENGTH);
+		fields[2] = new Field("", "FUNCTION_NAME", Types.CHAR,
+				MAX_IDENTIFIER_LENGTH);
+		fields[3] = new Field("", "REMARKS", Types.CHAR, MAX_IDENTIFIER_LENGTH);
+		fields[4] = new Field("", "FUNCTION_TYPE", Types.SMALLINT, 0);
+		fields[5] = new Field("", "SPECIFIC_NAME", Types.CHAR,
+				MAX_IDENTIFIER_LENGTH);
+
+		return getProceduresAndOrFunctions(fields, catalog, schemaPattern,
+				functionNamePattern, false, true);
+
+	}
+
+	public RowIdLifetime getRowIdLifetime() throws SQLException {
+		throw new NotYetImplementedException();
+	}
+
+	public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
+		throw new NotYetImplementedException();
+	}
+
+	public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
+		return true;
+	}
+
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
+	}
+
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+    public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
+    
+	public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException {
+		throw new NotYetImplementedException();
+	}
+
+	public boolean providesQueryObjectGenerator() throws SQLException {
+		return false;
+	}
+
+	protected int getJDBC4FunctionNoTableConstant() {
+		return functionNoTable;
+	}
+}

Modified: trunk/connector-j/src/com/mysql/jdbc/JDBC4PreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/JDBC4PreparedStatement.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/JDBC4PreparedStatement.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -75,12 +75,4 @@
 			throws SQLException {
 		JDBC4PreparedStatementHelper.setSQLXML(this, parameterIndex, xmlObject);
 	}
-
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
-
-	public void setPoolable(boolean poolable) throws SQLException {
-		throw new NotYetImplementedException();
-	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/JDBC4ResultSet.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/JDBC4ResultSet.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/JDBC4ResultSet.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -467,12 +467,51 @@
 		
 	}
 
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		checkClosed();
+		
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
-
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+    public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/JDBC4UpdatableResultSet.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/JDBC4UpdatableResultSet.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/JDBC4UpdatableResultSet.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -546,11 +546,51 @@
 		return this.isClosed;
 	}
 
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		checkClosed();
+		
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+    public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -164,11 +164,50 @@
 		}
 	}
 	
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class iface) throws SQLException {
+
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+	public Object unwrap(Class iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -32,6 +32,8 @@
 import java.io.Reader;
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.URL;
@@ -48,6 +50,7 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Locale;
+import java.util.Properties;
 import java.util.TimeZone;
 
 import com.mysql.jdbc.Statement.CancelTask;
@@ -81,6 +84,41 @@
  */
 public class PreparedStatement extends com.mysql.jdbc.Statement implements
 		java.sql.PreparedStatement {
+	private static final Constructor JDBC_4_PSTMT_2_ARG_CTOR;
+	private static final Constructor JDBC_4_PSTMT_3_ARG_CTOR;
+	private static final Constructor JDBC_4_PSTMT_4_ARG_CTOR;
+	
+	static {
+		if (Util.isJdbc4()) {
+			try {
+				JDBC_4_PSTMT_2_ARG_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4PreparedStatement")
+						.getConstructor(
+								new Class[] { Connection.class, String.class });
+				JDBC_4_PSTMT_3_ARG_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4PreparedStatement")
+						.getConstructor(
+								new Class[] { Connection.class, String.class,
+										String.class });
+				JDBC_4_PSTMT_4_ARG_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4PreparedStatement")
+						.getConstructor(
+								new Class[] { Connection.class, String.class,
+										String.class, ParseInfo.class });
+			} catch (SecurityException e) {
+				throw new RuntimeException(e);
+			} catch (NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException(e);
+			}
+		} else {
+			JDBC_4_PSTMT_2_ARG_CTOR = null;
+			JDBC_4_PSTMT_3_ARG_CTOR = null;
+			JDBC_4_PSTMT_4_ARG_CTOR = null;
+		}
+	}
+	
 	class BatchParams {
 		boolean[] isNull = null;
 
@@ -435,39 +473,55 @@
 	private boolean canRewrite = false;
 	
 	/**
-	 * Creates a prepared statement instance -- We need to provide factory-style methods
-	 * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
-	 * the class verifier complains when it tries to load JDBC4-only interface
-	 * classes that are present in JDBC4 method signatures.
+	 * Creates a prepared statement instance -- We need to provide factory-style
+	 * methods so we can support both JDBC3 (and older) and JDBC4 runtimes,
+	 * otherwise the class verifier complains when it tries to load JDBC4-only
+	 * interface classes that are present in JDBC4 method signatures.
 	 */
-	
+
+	protected static PreparedStatement getInstance(Connection conn,
+			String catalog) throws SQLException {
+		if (!Util.isJdbc4()) {
+			return new PreparedStatement(conn, catalog);
+		}
+
+		return (PreparedStatement) Util.handleNewInstance(
+				JDBC_4_PSTMT_2_ARG_CTOR, new Object[] { conn, catalog });
+	}
+
+	/**
+	 * Creates a prepared statement instance -- We need to provide factory-style
+	 * methods so we can support both JDBC3 (and older) and JDBC4 runtimes,
+	 * otherwise the class verifier complains when it tries to load JDBC4-only
+	 * interface classes that are present in JDBC4 method signatures.
+	 */
+
 	protected static PreparedStatement getInstance(Connection conn, String sql,
 			String catalog) throws SQLException {
 		if (!Util.isJdbc4()) {
 			return new PreparedStatement(conn, sql, catalog);
 		}
 
-		return (PreparedStatement)Util.getInstance("com.mysql.jdbc.JDBC4PreparedStatement", 
-				new Class[] {Connection.class, String.class, String.class}, 
-				new Object[] {conn, sql, catalog});
+		return (PreparedStatement) Util.handleNewInstance(
+				JDBC_4_PSTMT_3_ARG_CTOR, new Object[] { conn, sql, catalog });
 	}
 
 	/**
-	 * Creates a prepared statement instance -- We need to provide factory-style methods
-	 * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
-	 * the class verifier complains when it tries to load JDBC4-only interface
-	 * classes that are present in JDBC4 method signatures.
+	 * Creates a prepared statement instance -- We need to provide factory-style
+	 * methods so we can support both JDBC3 (and older) and JDBC4 runtimes,
+	 * otherwise the class verifier complains when it tries to load JDBC4-only
+	 * interface classes that are present in JDBC4 method signatures.
 	 */
-	
+
 	protected static PreparedStatement getInstance(Connection conn, String sql,
 			String catalog, ParseInfo cachedParseInfo) throws SQLException {
 		if (!Util.isJdbc4()) {
 			return new PreparedStatement(conn, sql, catalog, cachedParseInfo);
 		}
-		
-		return (PreparedStatement)Util.getInstance("com.mysql.jdbc.JDBC4PreparedStatement", 
-				new Class[] {Connection.class, String.class, String.class, ParseInfo.class}, 
-				new Object[] {conn, sql, catalog, cachedParseInfo});
+
+		return (PreparedStatement) Util.handleNewInstance(
+				JDBC_4_PSTMT_4_ARG_CTOR, new Object[] { conn, sql, catalog,
+						cachedParseInfo });
 	}
 	
 	/**
@@ -2108,10 +2162,6 @@
 		return this.isNull[paramIndex];
 	}
 
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
-
 	private final int readblock(InputStream i, byte[] b) throws SQLException {
 		try {
 			return i.read(b);

Modified: trunk/connector-j/src/com/mysql/jdbc/ResultSet.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ResultSet.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/ResultSet.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -24,6 +24,7 @@
  */
 package com.mysql.jdbc;
 
+import com.mysql.jdbc.PreparedStatement.ParseInfo;
 import com.mysql.jdbc.exceptions.NotYetImplementedException;
 import com.mysql.jdbc.profiler.ProfileEventSink;
 import com.mysql.jdbc.profiler.ProfilerEvent;
@@ -36,6 +37,7 @@
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 
+import java.lang.reflect.Constructor;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 
@@ -120,6 +122,44 @@
  */
 public class ResultSet implements java.sql.ResultSet {
 
+	private static final Constructor JDBC_4_RS_4_ARG_CTOR;
+	private static final Constructor JDBC_4_RS_6_ARG_CTOR;;
+	private static final Constructor JDBC_4_UPD_RS_6_ARG_CTOR;
+	
+	static {
+		if (Util.isJdbc4()) {
+			try {
+				JDBC_4_RS_4_ARG_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4ResultSet").getConstructor(
+						new Class[] { Long.TYPE, Long.TYPE,
+								com.mysql.jdbc.Connection.class,
+								com.mysql.jdbc.Statement.class });
+				JDBC_4_RS_6_ARG_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4ResultSet").getConstructor(
+						new Class[] { String.class, Field[].class,
+								RowData.class, com.mysql.jdbc.Connection.class,
+								com.mysql.jdbc.Statement.class });
+				JDBC_4_UPD_RS_6_ARG_CTOR = Class.forName(
+						"com.mysql.jdbc.JDBC4UpdatableResultSet")
+						.getConstructor(
+								new Class[] { String.class, Field[].class,
+										RowData.class,
+										com.mysql.jdbc.Connection.class,
+										com.mysql.jdbc.Statement.class });
+			} catch (SecurityException e) {
+				throw new RuntimeException(e);
+			} catch (NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException(e);
+			}
+		} else {
+			JDBC_4_RS_4_ARG_CTOR = null;
+			JDBC_4_RS_6_ARG_CTOR = null;
+			JDBC_4_UPD_RS_6_ARG_CTOR = null;
+		}
+	}
+	
 	/**
 	 * Epsillon between Float.MIN_VALUE and the double representation of said value.
 	 */
@@ -293,42 +333,39 @@
 			return new ResultSet(updateCount, updateID, conn, creatorStmt);
 		}
 
-		return (ResultSet) Util.getInstance(
-				"com.mysql.jdbc.JDBC4ResultSet", new Class[] {
-						Long.TYPE, Long.TYPE,
-						com.mysql.jdbc.Connection.class,
-						com.mysql.jdbc.Statement.class }, new Object[] {
-						new Long(updateCount), new Long(updateID), conn,
+		return (ResultSet) Util.handleNewInstance(JDBC_4_RS_4_ARG_CTOR,
+				new Object[] { new Long(updateCount), new Long(updateID), conn,
 						creatorStmt });
 	}
-	
+
 	/**
-	 * Creates a result set instance that represents a query result -- We need to
-	 * provide factory-style methods so we can support both JDBC3 (and older)
+	 * Creates a result set instance that represents a query result -- We need
+	 * to provide factory-style methods so we can support both JDBC3 (and older)
 	 * and JDBC4 runtimes, otherwise the class verifier complains when it tries
 	 * to load JDBC4-only interface classes that are present in JDBC4 method
 	 * signatures.
 	 */
 
-	protected static ResultSet getInstance(String catalog, Field[] fields, RowData tuples,
-			Connection conn, Statement creatorStmt, boolean isUpdatable) throws SQLException {
+	protected static ResultSet getInstance(String catalog, Field[] fields,
+			RowData tuples, Connection conn, Statement creatorStmt,
+			boolean isUpdatable) throws SQLException {
 		if (!Util.isJdbc4()) {
 			if (!isUpdatable) {
 				return new ResultSet(catalog, fields, tuples, conn, creatorStmt);
 			}
-			
-			return new UpdatableResultSet(catalog, fields, tuples, conn, creatorStmt);
+
+			return new UpdatableResultSet(catalog, fields, tuples, conn,
+					creatorStmt);
 		}
 
-		String className = isUpdatable ? "com.mysql.jdbc.JDBC4UpdatableResultSet" : "com.mysql.jdbc.JDBC4ResultSet";
-		
-		return (ResultSet) Util.getInstance(
-				className, new Class[] {
-						String.class, Field[].class,
-						RowData.class,
-						com.mysql.jdbc.Connection.class,
-						com.mysql.jdbc.Statement.class }, new Object[] {
-						catalog, fields, tuples, conn, creatorStmt });
+		if (!isUpdatable) {
+			return (ResultSet) Util
+					.handleNewInstance(JDBC_4_RS_6_ARG_CTOR, new Object[] {
+							catalog, fields, tuples, conn, creatorStmt });
+		}
+
+		return (ResultSet) Util.handleNewInstance(JDBC_4_UPD_RS_6_ARG_CTOR,
+				new Object[] { catalog, fields, tuples, conn, creatorStmt });
 	}
 
 	/**

Modified: trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -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 
@@ -19,8 +19,6 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-
-
  */
 package com.mysql.jdbc;
 
@@ -805,12 +803,50 @@
 			return "java.lang.Object"; //$NON-NLS-1$
 		}
 	}
-
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+	
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class iface) throws SQLException {
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+	public Object unwrap(Class iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -34,6 +34,8 @@
 import java.io.Reader;
 import java.io.UnsupportedEncodingException;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 
 import java.net.URL;
@@ -51,6 +53,7 @@
 
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Properties;
 import java.util.TimeZone;
 
 /**
@@ -61,6 +64,27 @@
  *          mmatthews Exp $
  */
 public class ServerPreparedStatement extends PreparedStatement {
+	private static final Constructor JDBC_4_SPS_CTOR;
+	
+	static {
+		if (Util.isJdbc4()) {
+			try {
+				JDBC_4_SPS_CTOR = Class.forName("com.mysql.jdbc.jdbc4.JDBC4ServerPreparedStatement")
+				.getConstructor(
+				new Class[] { Connection.class, String.class, String.class,
+						Integer.TYPE, Integer.TYPE});
+			} catch (SecurityException e) {
+				throw new RuntimeException(e);
+			} catch (NoSuchMethodException e) {
+				throw new RuntimeException(e);
+			} catch (ClassNotFoundException e) {
+				throw new RuntimeException(e);
+			} 
+		} else {
+			JDBC_4_SPS_CTOR = null;
+		}
+	}
+	
 	protected static final int BLOB_STREAM_READ_BUF_SIZE = 8192;
 
 	static class BatchedBindValues {
@@ -283,12 +307,25 @@
 					resultSetType, resultSetConcurrency);
 		}
 
-		return (ServerPreparedStatement) Util.getInstance(
-				"com.mysql.jdbc.jdbc4.JDBC4ServerPreparedStatement",
-				new Class[] { Connection.class, String.class, String.class,
-						Integer.TYPE, Integer.TYPE }, new Object[] { conn,
-						sql, catalog, new Integer(resultSetType),
-						new Integer(resultSetConcurrency) });
+		try {
+			return (ServerPreparedStatement) JDBC_4_SPS_CTOR.newInstance(new Object[] { conn,
+					sql, catalog, new Integer(resultSetType),
+					new Integer(resultSetConcurrency) });
+		} catch (IllegalArgumentException e) {
+			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+		} catch (InstantiationException e) {
+			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+		} catch (IllegalAccessException e) {
+			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+		} catch (InvocationTargetException e) {
+			Throwable target = e.getTargetException(); 
+			
+			if (target instanceof SQLException) {
+				throw (SQLException)target;
+			}
+			
+			throw new SQLException(target.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+		}
 	}
 
 	/**

Modified: trunk/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Statement.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/Statement.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -2344,11 +2344,51 @@
 		this.isPoolable = poolable;
 	}
 
-	public boolean isWrapperFor(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
+	/**
+     * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
+     * for an object that does. Returns false otherwise. If this implements the interface then return true,
+     * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
+     * object. If this does not implement the interface and is not a wrapper, return false.
+     * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
+     * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
+     * returns true then calling <code>unwrap</code> with the same argument should succeed.
+     *
+     * @param interfaces a Class defining an interface.
+     * @return true if this implements the interface or directly or indirectly wraps an object that does.
+     * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
+     * for an object with the given interface.
+     * @since 1.6
+     */
+	public boolean isWrapperFor(Class iface) throws SQLException {
+		checkClosed();
+		
+		// This works for classes that aren't actually wrapping
+		// anything
+		return iface.isInstance(this);
 	}
 
-	public Object unwrap(Class arg0) throws SQLException {
-		throw new NotYetImplementedException();
-	}
+    /**
+     * Returns an object that implements the given interface to allow access to non-standard methods,
+     * or standard methods not exposed by the proxy.
+     * The result may be either the object found to implement the interface or a proxy for that object.
+     * If the receiver implements the interface then that is the object. If the receiver is a wrapper
+     * and the wrapped object implements the interface then that is the object. Otherwise the object is
+     *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
+     * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
+     *
+     * @param iface A Class defining an interface that the result must implement.
+     * @return an object that implements the interface. May be a proxy for the actual implementing object.
+     * @throws java.sql.SQLException If no object found that implements the interface 
+     * @since 1.6
+     */
+	public Object unwrap(Class iface) throws java.sql.SQLException {
+    	try {
+    		// This works for classes that aren't actually wrapping
+    		// anything
+            return iface.cast(this);
+        } catch (ClassCastException cce) {
+            throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
+            		SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+        }
+    }
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/Util.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Util.java	2007-03-14 23:56:12 UTC (rev 6348)
+++ trunk/connector-j/src/com/mysql/jdbc/Util.java	2007-03-15 20:13:35 UTC (rev 6349)
@@ -27,6 +27,7 @@
 import java.io.ObjectInputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.sql.SQLException;
 import java.util.TimeZone;
@@ -322,16 +323,29 @@
 		return traceBuf.toString();
 	}
 	
+	public static Object getInstance(String className, Class[] argTypes, Object[] args) throws SQLException {
+		
+			try {
+				return handleNewInstance(Class.forName(className).getConstructor(argTypes), args);
+			} catch (SecurityException e) {
+				throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+			} catch (NoSuchMethodException e) {
+				throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+			} catch (ClassNotFoundException e) {
+				throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+	}
 	
-	public static Object getInstance(String className, Class[] argTypes, Object[] args) throws SQLException {
+	/**
+	 * Handles constructing new instance with the given constructor and wrapping
+	 * (or not, as required) the exceptions that could possibly be generated
+	 */
+	public static final Object handleNewInstance(Constructor ctor, Object[] args) throws SQLException {
 		try {
-			Class c = Class.forName(className);
-		
-			return c.getConstructor(argTypes).newInstance(args);
+			
+			return ctor.newInstance(args);
 		} catch (IllegalArgumentException e) {
 			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
-		} catch (SecurityException e) {
-			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
 		} catch (InstantiationException e) {
 			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
 		} catch (IllegalAccessException e) {
@@ -343,11 +357,11 @@
 				throw (SQLException)target;
 			}
 			
+			if (target instanceof ExceptionInInitializerError) {
+				target = ((ExceptionInInitializerError)target).getException();
+			}
+			
 			throw new SQLException(target.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
-		} catch (NoSuchMethodException e) {
-			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
-		} catch (ClassNotFoundException e) {
-			throw new SQLException(e.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
 		}
 	}
 	

Thread
Connector/J commit: r6349 - trunk/connector-j/src/com/mysql/jdbcmmatthews15 Mar