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/jdbc | mmatthews | 15 Mar |