List:Commits« Previous MessageNext Message »
From:mmatthews Date:September 19 2006 3:47am
Subject:Connector/J commit: r5749 - in trunk/connector-j: . src/com/mysql/jdbc src/com/mysql/jdbc/exceptions src/com/mysql/jdbc/exceptions/jdbc4 src/com/mysql...
View as plain text  
Added:
   trunk/connector-j/src/com/mysql/jdbc/MysqlSQLXML.java
   trunk/connector-j/src/com/mysql/jdbc/NClob.java
   trunk/connector-j/src/com/mysql/jdbc/exceptions/JDBC40NotYetImplementedException.java
   trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/
   trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java
  
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java
  
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java
  
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java
   trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java
   trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java
   trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java
  
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java
  
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java
   trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java
Modified:
   trunk/connector-j/CHANGES
   trunk/connector-j/src/com/mysql/jdbc/Blob.java
   trunk/connector-j/src/com/mysql/jdbc/BlobFromLocator.java
   trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
   trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java
   trunk/connector-j/src/com/mysql/jdbc/Clob.java
   trunk/connector-j/src/com/mysql/jdbc/Connection.java
   trunk/connector-j/src/com/mysql/jdbc/ConnectionProperties.java
   trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
   trunk/connector-j/src/com/mysql/jdbc/EscapeProcessor.java
   trunk/connector-j/src/com/mysql/jdbc/ExportControlled.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/ReplicationConnection.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/SQLError.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/StringUtils.java
   trunk/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java
   trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java
   trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
   trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java
   trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java
   trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
   trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
   trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java
   trunk/connector-j/src/testsuite/simple/StatementsTest.java
Log:
Merge of already complete JDBC-4.0 features from 5.1 branch to trunk, and merge from 5.0
to trunk.

Modified: trunk/connector-j/CHANGES
===================================================================
--- trunk/connector-j/CHANGES	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/CHANGES	2006-09-19 01:47:23 UTC (rev 5749)
@@ -24,6 +24,18 @@
 	  
 	- Driver now supports {call sp} (without "()" if procedure has no
 	  arguments).
+  
+	- Fixed BUG#22359 - Driver was using milliseconds for
+	  Statement.setQueryTimeout() when specification says argument is
+	  to be in seconds.
+	  
+	- Workaround for server crash when calling stored procedures
+	  via a server-side prepared statement (driver now detects 
+	  prepare(stored procedure) and substitutes client-side prepared 
+	  statement), addresses BUG#22297.
+	  
+	- Added new _ci collations to CharsetMapping, fixing 
+	  Bug#22456 - utf8_unicode_ci not working.
 	 
 07-26-06 - Version 5.0.3
 

Modified: trunk/connector-j/src/com/mysql/jdbc/Blob.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Blob.java	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/Blob.java	2006-09-19 01:47:23 UTC (rev 5749)
@@ -62,6 +62,13 @@
 	private boolean isClosed = false;
 
 	/**
+     * Creates a Blob without data
+     */
+    Blob() {
+        setBinaryData(Constants.EMPTY_BYTE_ARRAY);
+    }
+    
+	/**
 	 * Creates a BLOB encapsulating the given binary data
 	 * 
 	 * @param data

Modified: trunk/connector-j/src/com/mysql/jdbc/BlobFromLocator.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/BlobFromLocator.java	2006-09-19 01:45:03 UTC (rev
5748)
+++ trunk/connector-j/src/com/mysql/jdbc/BlobFromLocator.java	2006-09-19 01:47:23 UTC (rev
5749)
@@ -32,6 +32,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
 /**
  * The representation (mapping) in the JavaTM programming language of an SQL
  * BLOB value. An SQL BLOB is a built-in type that stores a Binary Large Object
@@ -668,4 +670,13 @@
 			super.close();
 		}
 	}
+
+	public void free() throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+		
+	}
+
+	public InputStream getBinaryStream(long pos, long length) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -34,9 +34,12 @@
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.Date;
+import java.sql.NClob;
 import java.sql.ParameterMetaData;
 import java.sql.Ref;
+import java.sql.RowId;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
@@ -48,6 +51,8 @@
 import java.util.List;
 import java.util.Map;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
 /**
  * Representation of stored procedures for JDBC
  * 
@@ -303,6 +308,14 @@
 				throws SQLException {
 			super(paramTypesRs);
 		}
+
+		public boolean isWrapperFor(Class arg0) throws SQLException {
+			throw new JDBC40NotYetImplementedException();
+		}
+
+		public Object unwrap(Class arg0) throws SQLException {
+			throw new JDBC40NotYetImplementedException();
+		}
 	}
 
 	private final static int NOT_OUTPUT_PARAMETER_INDICATOR = Integer.MIN_VALUE;
@@ -2076,4 +2089,272 @@
 		
 		return super.executeBatch();
 	}
+	
+	public RowId getRowId(String parameterName) throws SQLException {
+		ResultSet rs = getOutputParameters(0); // definitely not going to be
+		// from ?=
+
+		RowId retValue = rs.getRowId(fixParameterName(parameterName));
+
+		this.outputParamWasNull = rs.wasNull();
+
+		return retValue;
+		
+	}
+
+	public SQLXML getSQLXML(int parameterIndex) throws SQLException {
+		ResultSet rs = getOutputParameters(parameterIndex);
+
+		SQLXML retValue = rs
+				.getSQLXML(mapOutputParameterIndexToRsIndex(parameterIndex));
+
+		this.outputParamWasNull = rs.wasNull();
+
+		return retValue;
+		
+	}
+
+	public SQLXML getSQLXML(String parameterName) throws SQLException {
+		ResultSet rs = getOutputParameters(0); // definitely not going to be
+		// from ?=
+
+		SQLXML retValue = rs.getSQLXML(fixParameterName(parameterName));
+
+		this.outputParamWasNull = rs.wasNull();
+
+		return retValue;
+	}
+
+	public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
+		setAsciiStream(getNamedParamIndex(parameterName, false), x);
+		
+	}
+
+	public void setAsciiStream(String parameterName, InputStream x, long length) throws
SQLException {
+		setAsciiStream(getNamedParamIndex(parameterName, false), x, length);
+		
+	}
+
+	public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
+		setBinaryStream(getNamedParamIndex(parameterName, false), x);
+		
+	}
+
+	public void setBinaryStream(String parameterName, InputStream x, long length) throws
SQLException {
+		setBinaryStream(getNamedParamIndex(parameterName, false), x, length);
+		
+	}
+
+	public void setBlob(String parameterName, Blob x) throws SQLException {
+		setBlob(getNamedParamIndex(parameterName, false), x);
+		
+	}
+
+	public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
+		setBlob(getNamedParamIndex(parameterName, false), inputStream);
+		
+	}
+
+	public void setBlob(String parameterName, InputStream inputStream, long length) throws
SQLException {
+		setBlob(getNamedParamIndex(parameterName, false), inputStream, length);
+		
+	}
+
+	public void setCharacterStream(String parameterName, Reader reader) throws SQLException
{
+		setCharacterStream(getNamedParamIndex(parameterName, false), reader);
+		
+	}
+
+	public void setCharacterStream(String parameterName, Reader reader, long length) throws
SQLException {
+		setCharacterStream(getNamedParamIndex(parameterName, false), reader, length);
+		
+	}
+
+	public void setClob(String parameterName, Clob x) throws SQLException {
+		setClob(getNamedParamIndex(parameterName, false), x);
+		
+	}
+
+	public void setClob(String parameterName, Reader reader) throws SQLException {
+		setClob(getNamedParamIndex(parameterName, false), reader);
+		
+	}
+
+	public void setClob(String parameterName, Reader reader, long length) throws
SQLException {
+		setClob(getNamedParamIndex(parameterName, false), reader, length);
+		
+	}
+
+	public void setNCharacterStream(String parameterName, Reader value) throws SQLException
{
+		setNCharacterStream(getNamedParamIndex(parameterName, false), value);
+		
+	}
+
+	public void setNCharacterStream(String parameterName, Reader value, long length) throws
SQLException {
+		setNCharacterStream(getNamedParamIndex(parameterName, false), value, length);
+		
+	}
+
+	public void setNClob(String parameterName, NClob value) throws SQLException {
+		setNClob(getNamedParamIndex(parameterName, false), value);
+		
+	}
+
+	public void setNClob(String parameterName, Reader reader) throws SQLException {
+		setNClob(getNamedParamIndex(parameterName, false), reader);
+		
+	}
+
+	public void setNClob(String parameterName, Reader reader, long length) throws
SQLException {
+		setNClob(getNamedParamIndex(parameterName, false), reader, length);
+		
+	}
+
+	public void setNString(String parameterName, String value) throws SQLException {
+		setNString(getNamedParamIndex(parameterName, false), value);
+		
+	}
+
+	public void setRowId(String parameterName, RowId x) throws SQLException {
+		setRowId(getNamedParamIndex(parameterName, false), x);
+		
+	}
+
+	public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
+		setSQLXML(getNamedParamIndex(parameterName, false), xmlObject);
+		
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+		
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+		
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getCharacterStream(int)
+	 */
+	public Reader getCharacterStream(int parameterIndex) throws SQLException {
+	    ResultSet rs = getOutputParameters(parameterIndex);
+	
+	    Reader retValue = rs
+	            .getCharacterStream(mapOutputParameterIndexToRsIndex(parameterIndex));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getCharacterStream(java.lang.String)
+	 */
+	public Reader getCharacterStream(String parameterName) throws SQLException {
+	    ResultSet rs = getOutputParameters(0); // definitely not going to be
+	    // from ?=
+	
+	    Reader retValue = rs.getCharacterStream(fixParameterName(parameterName));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getNCharacterStream(int)
+	 */
+	public Reader getNCharacterStream(int parameterIndex) throws SQLException {
+	    ResultSet rs = getOutputParameters(parameterIndex);
+	
+	    Reader retValue = rs
+	            .getNCharacterStream(mapOutputParameterIndexToRsIndex(parameterIndex));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getNCharacterStream(java.lang.String)
+	 */
+	public Reader getNCharacterStream(String parameterName) throws SQLException {
+	    ResultSet rs = getOutputParameters(0); // definitely not going to be
+	    // from ?=
+	
+	    Reader retValue = rs.getNCharacterStream(fixParameterName(parameterName));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getNClob(int)
+	 */
+	public NClob getNClob(int parameterIndex) throws SQLException {
+	    ResultSet rs = getOutputParameters(parameterIndex);
+	
+	    NClob retValue = rs
+	            .getNClob(mapOutputParameterIndexToRsIndex(parameterIndex));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getNClob(java.lang.String)
+	 */
+	public NClob getNClob(String parameterName) throws SQLException {
+	    ResultSet rs = getOutputParameters(0); // definitely not going to be
+	    // from ?=
+	
+	    NClob retValue = rs.getNClob(fixParameterName(parameterName));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getNString(int)
+	 */
+	public String getNString(int parameterIndex) throws SQLException {
+	    ResultSet rs = getOutputParameters(parameterIndex);
+	
+	    String retValue = rs
+	            .getNString(mapOutputParameterIndexToRsIndex(parameterIndex));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	/**
+	 * @see java.sql.CallableStatement#getNString(java.lang.String)
+	 */
+	public String getNString(String parameterName) throws SQLException {
+	    ResultSet rs = getOutputParameters(0); // definitely not going to be
+	    // from ?=
+	
+	    String retValue = rs.getNString(fixParameterName(parameterName));
+	
+	    this.outputParamWasNull = rs.wasNull();
+	
+	    return retValue;
+	}
+
+	public RowId getRowId(int parameterIndex) throws SQLException {
+		ResultSet rs = getOutputParameters(parameterIndex);
+
+		RowId retValue = rs
+				.getRowId(mapOutputParameterIndexToRsIndex(parameterIndex));
+
+		this.outputParamWasNull = rs.wasNull();
+
+		return retValue;
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java	2006-09-19 01:45:03 UTC (rev
5748)
+++ trunk/connector-j/src/com/mysql/jdbc/CharsetMapping.java	2006-09-19 01:47:23 UTC (rev
5749)
@@ -234,7 +234,7 @@
 
 		MULTIBYTE_CHARSETS = Collections.unmodifiableMap(tempMapMulti);
 
-		INDEX_TO_CHARSET = new String[99];
+		INDEX_TO_CHARSET = new String[211];
 
 		try {
 			INDEX_TO_CHARSET[1] = getJavaEncodingForMysqlEncoding("big5", null);
@@ -398,6 +398,84 @@
 					null);
 			INDEX_TO_CHARSET[98] = getJavaEncodingForMysqlEncoding("eucjpms",
 					null);
+			
+			INDEX_TO_CHARSET[128] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[129] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[130] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[131] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[132] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[133] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[134] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[135] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[136] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[137] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[138] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[139] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[140] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[141] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[142] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[143] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[144] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[145] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+			INDEX_TO_CHARSET[146] = getJavaEncodingForMysqlEncoding("ucs2",
+					null);
+
+			INDEX_TO_CHARSET[192] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[193] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[194] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[195] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[196] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[197] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[198] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[199] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[200] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[201] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[202] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[203] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[204] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[205] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[206] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[207] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[208] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[209] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
+			INDEX_TO_CHARSET[210] = getJavaEncodingForMysqlEncoding("utf8",
+					null);
 		} catch (SQLException sqlEx) {
 			// ignore, it won't happen in this case
 		}

Modified: trunk/connector-j/src/com/mysql/jdbc/Clob.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Clob.java	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/Clob.java	2006-09-19 01:47:23 UTC (rev 5749)
@@ -33,6 +33,8 @@
 
 import java.sql.SQLException;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
 /**
  * Simplistic implementation of java.sql.Clob for MySQL Connector/J
  * 
@@ -42,6 +44,10 @@
 public class Clob implements java.sql.Clob, OutputStreamWatcher, WriterWatcher {
 	private String charData;
 
+    Clob() {
+        this.charData = "";
+    }
+    
 	Clob(String charDataInit) {
 		this.charData = charDataInit;
 	}
@@ -287,4 +293,12 @@
 
 		this.charData = out.toString();
 	}
+
+	public void free() throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Reader getCharacterStream(long pos, long length) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Connection.java	2006-09-19 01:45:03 UTC (rev
5748)
+++ trunk/connector-j/src/com/mysql/jdbc/Connection.java	2006-09-19 01:47:23 UTC (rev
5749)
@@ -24,6 +24,7 @@
  */
 package com.mysql.jdbc;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 import com.mysql.jdbc.log.Log;
 import com.mysql.jdbc.log.LogFactory;
 import com.mysql.jdbc.log.NullLogger;
@@ -42,14 +43,19 @@
 
 import java.net.URL;
 
+import java.sql.BaseQuery;
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.Date;
+import java.sql.NClob;
 import java.sql.ParameterMetaData;
 import java.sql.Ref;
+import java.sql.SQLClientInfoException;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
+import java.sql.SQLXML;
 import java.sql.Savepoint;
+import java.sql.Struct;
 import java.sql.Time;
 import java.sql.Timestamp;
 
@@ -142,883 +148,6 @@
 	}
 
 	/**
-	 * Wrapper class for UltraDev CallableStatements that are really
-	 * PreparedStatments. Nice going, UltraDev developers.
-	 */
-	class UltraDevWorkAround implements java.sql.CallableStatement {
-		private java.sql.PreparedStatement delegate = null;
-
-		UltraDevWorkAround(java.sql.PreparedStatement pstmt) {
-			this.delegate = pstmt;
-		}
-
-		public void addBatch() throws SQLException {
-			this.delegate.addBatch();
-		}
-
-		public void addBatch(java.lang.String p1) throws SQLException {
-			this.delegate.addBatch(p1);
-		}
-
-		public void cancel() throws SQLException {
-			this.delegate.cancel();
-		}
-
-		public void clearBatch() throws SQLException {
-			this.delegate.clearBatch();
-		}
-
-		public void clearParameters() throws SQLException {
-			this.delegate.clearParameters();
-		}
-
-		public void clearWarnings() throws SQLException {
-			this.delegate.clearWarnings();
-		}
-
-		public void close() throws SQLException {
-			this.delegate.close();
-		}
-
-		public boolean execute() throws SQLException {
-			return this.delegate.execute();
-		}
-
-		public boolean execute(java.lang.String p1) throws SQLException {
-			return this.delegate.execute(p1);
-		}
-
-		/**
-		 * @see Statement#execute(String, int)
-		 */
-		public boolean execute(String arg0, int arg1) throws SQLException {
-			return this.delegate.execute(arg0, arg1);
-		}
-
-		/**
-		 * @see Statement#execute(String, int[])
-		 */
-		public boolean execute(String arg0, int[] arg1) throws SQLException {
-			return this.delegate.execute(arg0, arg1);
-		}
-
-		/**
-		 * @see Statement#execute(String, String[])
-		 */
-		public boolean execute(String arg0, String[] arg1) throws SQLException {
-			return this.delegate.execute(arg0, arg1);
-		}
-
-		public int[] executeBatch() throws SQLException {
-			return this.delegate.executeBatch();
-		}
-
-		public java.sql.ResultSet executeQuery() throws SQLException {
-			return this.delegate.executeQuery();
-		}
-
-		public java.sql.ResultSet executeQuery(java.lang.String p1)
-				throws SQLException {
-			return this.delegate.executeQuery(p1);
-		}
-
-		public int executeUpdate() throws SQLException {
-			return this.delegate.executeUpdate();
-		}
-
-		public int executeUpdate(java.lang.String p1) throws SQLException {
-			return this.delegate.executeUpdate(p1);
-		}
-
-		/**
-		 * @see Statement#executeUpdate(String, int)
-		 */
-		public int executeUpdate(String arg0, int arg1) throws SQLException {
-			return this.delegate.executeUpdate(arg0, arg1);
-		}
-
-		/**
-		 * @see Statement#executeUpdate(String, int[])
-		 */
-		public int executeUpdate(String arg0, int[] arg1) throws SQLException {
-			return this.delegate.executeUpdate(arg0, arg1);
-		}
-
-		/**
-		 * @see Statement#executeUpdate(String, String[])
-		 */
-		public int executeUpdate(String arg0, String[] arg1)
-				throws SQLException {
-			return this.delegate.executeUpdate(arg0, arg1);
-		}
-
-		public java.sql.Array getArray(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getArray(String)
-		 */
-		public java.sql.Array getArray(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.math.BigDecimal getBigDecimal(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * DOCUMENT ME!
-		 * 
-		 * @param p1
-		 *            DOCUMENT ME!
-		 * @param p2
-		 *            DOCUMENT ME!
-		 * @return DOCUMENT ME!
-		 * @throws SQLException
-		 *             DOCUMENT ME!
-		 * @deprecated
-		 */
-		public java.math.BigDecimal getBigDecimal(int p1, int p2)
-				throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getBigDecimal(String)
-		 */
-		public BigDecimal getBigDecimal(String arg0) throws SQLException {
-			return null;
-		}
-
-		public java.sql.Blob getBlob(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getBlob(String)
-		 */
-		public java.sql.Blob getBlob(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public boolean getBoolean(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getBoolean(String)
-		 */
-		public boolean getBoolean(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public byte getByte(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getByte(String)
-		 */
-		public byte getByte(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public byte[] getBytes(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getBytes(String)
-		 */
-		public byte[] getBytes(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.sql.Clob getClob(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getClob(String)
-		 */
-		public Clob getClob(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.sql.Connection getConnection() throws SQLException {
-			return this.delegate.getConnection();
-		}
-
-		public java.sql.Date getDate(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public java.sql.Date getDate(int p1, final Calendar p2)
-				throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getDate(String)
-		 */
-		public Date getDate(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#getDate(String, Calendar)
-		 */
-		public Date getDate(String arg0, Calendar arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public double getDouble(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getDouble(String)
-		 */
-		public double getDouble(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public int getFetchDirection() throws SQLException {
-			return this.delegate.getFetchDirection();
-		}
-
-		public int getFetchSize() throws java.sql.SQLException {
-			return this.delegate.getFetchSize();
-		}
-
-		public float getFloat(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getFloat(String)
-		 */
-		public float getFloat(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see Statement#getGeneratedKeys()
-		 */
-		public java.sql.ResultSet getGeneratedKeys() throws SQLException {
-			return this.delegate.getGeneratedKeys();
-		}
-
-		public int getInt(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getInt(String)
-		 */
-		public int getInt(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public long getLong(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getLong(String)
-		 */
-		public long getLong(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public int getMaxFieldSize() throws SQLException {
-			return this.delegate.getMaxFieldSize();
-		}
-
-		public int getMaxRows() throws SQLException {
-			return this.delegate.getMaxRows();
-		}
-
-		public java.sql.ResultSetMetaData getMetaData() throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public boolean getMoreResults() throws SQLException {
-			return this.delegate.getMoreResults();
-		}
-
-		/**
-		 * @see Statement#getMoreResults(int)
-		 */
-		public boolean getMoreResults(int arg0) throws SQLException {
-			return this.delegate.getMoreResults();
-		}
-
-		public java.lang.Object getObject(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public java.lang.Object getObject(int p1, final java.util.Map p2)
-				throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getObject(String)
-		 */
-		public Object getObject(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#getObject(String, Map)
-		 */
-		public Object getObject(String arg0, Map arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see PreparedStatement#getParameterMetaData()
-		 */
-		public ParameterMetaData getParameterMetaData() throws SQLException {
-			return this.delegate.getParameterMetaData();
-		}
-
-		public int getQueryTimeout() throws SQLException {
-			return this.delegate.getQueryTimeout();
-		}
-
-		public java.sql.Ref getRef(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getRef(String)
-		 */
-		public Ref getRef(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.sql.ResultSet getResultSet() throws SQLException {
-			return this.delegate.getResultSet();
-		}
-
-		public int getResultSetConcurrency() throws SQLException {
-			return this.delegate.getResultSetConcurrency();
-		}
-
-		/**
-		 * @see Statement#getResultSetHoldability()
-		 */
-		public int getResultSetHoldability() throws SQLException {
-			return this.delegate.getResultSetHoldability();
-		}
-
-		public int getResultSetType() throws SQLException {
-			return this.delegate.getResultSetType();
-		}
-
-		public short getShort(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getShort(String)
-		 */
-		public short getShort(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.lang.String getString(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getString(String)
-		 */
-		public String getString(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.sql.Time getTime(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public java.sql.Time getTime(int p1, final java.util.Calendar p2)
-				throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getTime(String)
-		 */
-		public Time getTime(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#getTime(String, Calendar)
-		 */
-		public Time getTime(String arg0, Calendar arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.sql.Timestamp getTimestamp(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public java.sql.Timestamp getTimestamp(int p1,
-				final java.util.Calendar p2) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#getTimestamp(String)
-		 */
-		public Timestamp getTimestamp(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#getTimestamp(String, Calendar)
-		 */
-		public Timestamp getTimestamp(String arg0, Calendar arg1)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public int getUpdateCount() throws SQLException {
-			return this.delegate.getUpdateCount();
-		}
-
-		/**
-		 * @see CallableStatement#getURL(int)
-		 */
-		public URL getURL(int arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#getURL(String)
-		 */
-		public URL getURL(String arg0) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public java.sql.SQLWarning getWarnings() throws SQLException {
-			return this.delegate.getWarnings();
-		}
-
-		public void registerOutParameter(int p1, int p2) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public void registerOutParameter(int p1, int p2, int p3)
-				throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public void registerOutParameter(int p1, int p2, java.lang.String p3)
-				throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		/**
-		 * @see CallableStatement#registerOutParameter(String, int)
-		 */
-		public void registerOutParameter(String arg0, int arg1)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#registerOutParameter(String, int, int)
-		 */
-		public void registerOutParameter(String arg0, int arg1, int arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#registerOutParameter(String, int, String)
-		 */
-		public void registerOutParameter(String arg0, int arg1, String arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setArray(int p1, final java.sql.Array p2)
-				throws SQLException {
-			this.delegate.setArray(p1, p2);
-		}
-
-		public void setAsciiStream(int p1, final java.io.InputStream p2, int p3)
-				throws SQLException {
-			this.delegate.setAsciiStream(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setAsciiStream(String, InputStream, int)
-		 */
-		public void setAsciiStream(String arg0, InputStream arg1, int arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setBigDecimal(int p1, final java.math.BigDecimal p2)
-				throws SQLException {
-			this.delegate.setBigDecimal(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setBigDecimal(String, BigDecimal)
-		 */
-		public void setBigDecimal(String arg0, BigDecimal arg1)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setBinaryStream(int p1, final java.io.InputStream p2, int p3)
-				throws SQLException {
-			this.delegate.setBinaryStream(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setBinaryStream(String, InputStream, int)
-		 */
-		public void setBinaryStream(String arg0, InputStream arg1, int arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setBlob(int p1, final java.sql.Blob p2) throws SQLException {
-			this.delegate.setBlob(p1, p2);
-		}
-
-		public void setBoolean(int p1, boolean p2) throws SQLException {
-			this.delegate.setBoolean(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setBoolean(String, boolean)
-		 */
-		public void setBoolean(String arg0, boolean arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setByte(int p1, byte p2) throws SQLException {
-			this.delegate.setByte(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setByte(String, byte)
-		 */
-		public void setByte(String arg0, byte arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setBytes(int p1, byte[] p2) throws SQLException {
-			this.delegate.setBytes(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setBytes(String, byte[])
-		 */
-		public void setBytes(String arg0, byte[] arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setCharacterStream(int p1, final java.io.Reader p2, int p3)
-				throws SQLException {
-			this.delegate.setCharacterStream(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setCharacterStream(String, Reader, int)
-		 */
-		public void setCharacterStream(String arg0, Reader arg1, int arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setClob(int p1, final java.sql.Clob p2) throws SQLException {
-			this.delegate.setClob(p1, p2);
-		}
-
-		public void setCursorName(java.lang.String p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public void setDate(int p1, final java.sql.Date p2) throws SQLException {
-			this.delegate.setDate(p1, p2);
-		}
-
-		public void setDate(int p1, final java.sql.Date p2,
-				final java.util.Calendar p3) throws SQLException {
-			this.delegate.setDate(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setDate(String, Date)
-		 */
-		public void setDate(String arg0, Date arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#setDate(String, Date, Calendar)
-		 */
-		public void setDate(String arg0, Date arg1, Calendar arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setDouble(int p1, double p2) throws SQLException {
-			this.delegate.setDouble(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setDouble(String, double)
-		 */
-		public void setDouble(String arg0, double arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setEscapeProcessing(boolean p1) throws SQLException {
-			this.delegate.setEscapeProcessing(p1);
-		}
-
-		public void setFetchDirection(int p1) throws SQLException {
-			this.delegate.setFetchDirection(p1);
-		}
-
-		public void setFetchSize(int p1) throws SQLException {
-			this.delegate.setFetchSize(p1);
-		}
-
-		public void setFloat(int p1, float p2) throws SQLException {
-			this.delegate.setFloat(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setFloat(String, float)
-		 */
-		public void setFloat(String arg0, float arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setInt(int p1, int p2) throws SQLException {
-			this.delegate.setInt(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setInt(String, int)
-		 */
-		public void setInt(String arg0, int arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setLong(int p1, long p2) throws SQLException {
-			this.delegate.setLong(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setLong(String, long)
-		 */
-		public void setLong(String arg0, long arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setMaxFieldSize(int p1) throws SQLException {
-			this.delegate.setMaxFieldSize(p1);
-		}
-
-		public void setMaxRows(int p1) throws SQLException {
-			this.delegate.setMaxRows(p1);
-		}
-
-		public void setNull(int p1, int p2) throws SQLException {
-			this.delegate.setNull(p1, p2);
-		}
-
-		public void setNull(int p1, int p2, java.lang.String p3)
-				throws SQLException {
-			this.delegate.setNull(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setNull(String, int)
-		 */
-		public void setNull(String arg0, int arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#setNull(String, int, String)
-		 */
-		public void setNull(String arg0, int arg1, String arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setObject(int p1, final java.lang.Object p2)
-				throws SQLException {
-			this.delegate.setObject(p1, p2);
-		}
-
-		public void setObject(int p1, final java.lang.Object p2, int p3)
-				throws SQLException {
-			this.delegate.setObject(p1, p2, p3);
-		}
-
-		public void setObject(int p1, final java.lang.Object p2, int p3, int p4)
-				throws SQLException {
-			this.delegate.setObject(p1, p2, p3, p4);
-		}
-
-		/**
-		 * @see CallableStatement#setObject(String, Object)
-		 */
-		public void setObject(String arg0, Object arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#setObject(String, Object, int)
-		 */
-		public void setObject(String arg0, Object arg1, int arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#setObject(String, Object, int, int)
-		 */
-		public void setObject(String arg0, Object arg1, int arg2, int arg3)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setQueryTimeout(int p1) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public void setRef(int p1, final Ref p2) throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-
-		public void setShort(int p1, short p2) throws SQLException {
-			this.delegate.setShort(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setShort(String, short)
-		 */
-		public void setShort(String arg0, short arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setString(int p1, java.lang.String p2)
-				throws java.sql.SQLException {
-			this.delegate.setString(p1, p2);
-		}
-
-		/**
-		 * @see CallableStatement#setString(String, String)
-		 */
-		public void setString(String arg0, String arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setTime(int p1, final java.sql.Time p2) throws SQLException {
-			this.delegate.setTime(p1, p2);
-		}
-
-		public void setTime(int p1, final java.sql.Time p2,
-				final java.util.Calendar p3) throws SQLException {
-			this.delegate.setTime(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setTime(String, Time)
-		 */
-		public void setTime(String arg0, Time arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#setTime(String, Time, Calendar)
-		 */
-		public void setTime(String arg0, Time arg1, Calendar arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public void setTimestamp(int p1, final java.sql.Timestamp p2)
-				throws SQLException {
-			this.delegate.setTimestamp(p1, p2);
-		}
-
-		public void setTimestamp(int p1, final java.sql.Timestamp p2,
-				final java.util.Calendar p3) throws SQLException {
-			this.delegate.setTimestamp(p1, p2, p3);
-		}
-
-		/**
-		 * @see CallableStatement#setTimestamp(String, Timestamp)
-		 */
-		public void setTimestamp(String arg0, Timestamp arg1)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * @see CallableStatement#setTimestamp(String, Timestamp, Calendar)
-		 */
-		public void setTimestamp(String arg0, Timestamp arg1, Calendar arg2)
-				throws SQLException {
-			throw new NotImplemented();
-		}
-
-		/**
-		 * DOCUMENT ME!
-		 * 
-		 * @param p1
-		 *            DOCUMENT ME!
-		 * @param p2
-		 *            DOCUMENT ME!
-		 * @param p3
-		 *            DOCUMENT ME!
-		 * @throws SQLException
-		 *             DOCUMENT ME!
-		 * @deprecated
-		 */
-		public void setUnicodeStream(int p1, final java.io.InputStream p2,
-				int p3) throws SQLException {
-			this.delegate.setUnicodeStream(p1, p2, p3);
-		}
-
-		/**
-		 * @see PreparedStatement#setURL(int, URL)
-		 */
-		public void setURL(int arg0, URL arg1) throws SQLException {
-			this.delegate.setURL(arg0, arg1);
-		}
-
-		/**
-		 * @see CallableStatement#setURL(String, URL)
-		 */
-		public void setURL(String arg0, URL arg1) throws SQLException {
-			throw new NotImplemented();
-		}
-
-		public boolean wasNull() throws SQLException {
-			throw SQLError.createSQLException("Not supported");
-		}
-	}
-
-	/**
 	 * Marker for character set converter not being available (not written,
 	 * multibyte, etc) Used to prevent multiple instantiation requests.
 	 */
@@ -1741,6 +870,12 @@
 
 	private boolean canHandleAsServerPreparedStatementNoCache(String sql) 
 		throws SQLException {
+		
+		// Can't use server-side prepare for CALL
+		if (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "CALL")) {
+			return false;
+		}
+		
 		boolean canHandleAsStatement = true;
 		
 		if (!versionMeetsMinimum(5, 0, 7) && 
@@ -2084,18 +1219,25 @@
 	 */
 	public PreparedStatement clientPrepareStatement(String sql,
 			int resultSetType, int resultSetConcurrency) throws SQLException {
+		return clientPrepareStatement(sql, resultSetType, resultSetConcurrency, true);
+	}
+	
+	protected PreparedStatement clientPrepareStatement(String sql,
+			int resultSetType, int resultSetConcurrency, 
+			boolean processEscapeCodesIfNeeded) throws SQLException {
 		checkClosed();
 
+		String nativeSql = processEscapeCodesIfNeeded &&
getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql;
+		
 		PreparedStatement pStmt = null;
 
 		if (getCachePreparedStatements()) {
 			synchronized (this.cachedPreparedStatementParams) {
 				PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo)
this.cachedPreparedStatementParams
-						.get(sql);
+						.get(nativeSql);
 	
 				if (pStmtInfo == null) {
-					pStmt = new com.mysql.jdbc.PreparedStatement(this, 
-							getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql,
+					pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql,
 							this.database);
 	
 					PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo();
@@ -2124,17 +1266,17 @@
 							}
 						}
 	
-						this.cachedPreparedStatementParams.put(sql, pStmt
+						this.cachedPreparedStatementParams.put(nativeSql, pStmt
 								.getParseInfo());
 					}
 				} else {
 					pStmtInfo.lastUsed = System.currentTimeMillis();
-					pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
+					pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql,
 							this.database, pStmtInfo);
 				}
 			}
 		} else {
-			pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
+			pStmt = new com.mysql.jdbc.PreparedStatement(this, nativeSql,
 					this.database);
 		}
 
@@ -2327,6 +1469,15 @@
 					String serverEncodingToSet = 
 						CharsetMapping.INDEX_TO_CHARSET[this.io.serverCharsetIndex];
 					
+
+					if (serverEncodingToSet == null || serverEncodingToSet.length() == 0) {
+						throw SQLError.createSQLException(
+								"Unknown initial character set index '"
+										+ this.io.serverCharsetIndex
+										+ "' received from server. Initial client character set can be forced via the
'characterEncoding' property.",
+								SQLError.SQL_STATE_GENERAL_ERROR);
+					}
+					
 					if (versionMeetsMinimum(4, 1, 0) && 
 							"ISO8859_1".equalsIgnoreCase(serverEncodingToSet)) {
 						serverEncodingToSet = "Cp1252";
@@ -4405,9 +3556,6 @@
 	 */
 	public java.sql.CallableStatement prepareCall(String sql)
 			throws SQLException {
-		if (this.getUseUltraDevWorkAround()) {
-			return new UltraDevWorkAround(prepareStatement(sql));
-		}
 
 		return prepareCall(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY,
 				java.sql.ResultSet.CONCUR_READ_ONLY);
@@ -4575,14 +3723,17 @@
 					if (pStmt == null) {
 						try {
 							pStmt = new com.mysql.jdbc.ServerPreparedStatement(this, nativeSql,
-									this.database);
+									this.database, resultSetType, resultSetConcurrency);
 							if (sql.length() < getPreparedStatementCacheSqlLimit()) {
 								((com.mysql.jdbc.ServerPreparedStatement)pStmt).isCached = true;
 							}
+							
+							pStmt.setResultSetType(resultSetType);
+							pStmt.setResultSetConcurrency(resultSetConcurrency);
 						} catch (SQLException sqlEx) {
 							// Punt, if necessary
 							if (getEmulateUnsupportedPstmts()) {
-								pStmt = clientPrepareStatement(nativeSql);
+								pStmt = clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency,
false);
 								
 								if (sql.length() < getPreparedStatementCacheSqlLimit()) {
 									this.serverSideStatementCheckCache.put(sql, Boolean.FALSE);
@@ -4596,24 +3747,23 @@
 			} else {
 				try {
 					pStmt = new com.mysql.jdbc.ServerPreparedStatement(this, nativeSql,
-							this.database);
+							this.database, resultSetType, resultSetConcurrency);
+					
+					pStmt.setResultSetType(resultSetType);
+					pStmt.setResultSetConcurrency(resultSetConcurrency);
 				} catch (SQLException sqlEx) {
 					// Punt, if necessary
 					if (getEmulateUnsupportedPstmts()) {
-						pStmt = clientPrepareStatement(nativeSql);
+						pStmt = clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency,
false);
 					} else {
 						throw sqlEx;
 					}
 				}
 			}
 		} else {
-			pStmt = clientPrepareStatement(nativeSql);
+			pStmt = clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
 		}
-
-
-		pStmt.setResultSetType(resultSetType);
-		pStmt.setResultSetConcurrency(resultSetConcurrency);
-
+		
 		return pStmt;
 	}
 
@@ -4749,9 +3899,11 @@
 
 	}
 
-	protected void recachePreparedStatement(ServerPreparedStatement pstmt) {
-		synchronized (this.serverSideStatementCache) {
-			this.serverSideStatementCache.put(pstmt.originalSql, pstmt);
+	protected void recachePreparedStatement(ServerPreparedStatement pstmt) throws
SQLException {
+		if (pstmt.isPoolable()) {
+			synchronized (this.serverSideStatementCache) {
+				this.serverSideStatementCache.put(pstmt.originalSql, pstmt);
+			}
 		}
 	}
 
@@ -5150,10 +4302,15 @@
 	 *             DOCUMENT ME!
 	 */
 	public ServerPreparedStatement serverPrepare(String sql)
-			throws SQLException {
-		return new ServerPreparedStatement(this, sql, this.getCatalog());
-	}
+		throws SQLException {
 
+		String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql;
+
+		return new ServerPreparedStatement(this, nativeSql, this.getCatalog(),
+				java.sql.ResultSet.TYPE_SCROLL_SENSITIVE,
+				java.sql.ResultSet.CONCUR_READ_ONLY);
+}
+
 	protected boolean serverSupportsConvertFn() throws SQLException {
 		return versionMeetsMinimum(4, 0, 2);
 	}
@@ -5660,4 +4817,73 @@
 	public boolean hasTriedMaster() {
 		return this.hasTriedMasterFlag;
 	}
+
+	public java.sql.Array createArrayOf(String typeName, Object[] elements) throws
SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public BaseQuery createQueryObject(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public BaseQuery createQueryObject(Class arg0, java.sql.Connection arg1) throws
SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public SQLXML createSQLXML() throws SQLException {
+		return new MysqlSQLXML();
+	}
+
+	public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Properties getClientInfo() throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public String getClientInfo(String name) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public boolean isValid(int timeout) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public void setClientInfo(Properties properties) throws SQLClientInfoException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public void setClientInfo(String name, String value) throws SQLClientInfoException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	/**
+	 * @see java.sql.Connection#createBlob()
+	 */
+	public Blob createBlob() {
+	    return new com.mysql.jdbc.Blob();
+	}
+
+	/**
+	 * @see java.sql.Connection#createClob()
+	 */
+	public Clob createClob() {
+	    return new com.mysql.jdbc.Clob();
+	}
+
+	/**
+	 * @see java.sql.Connection#createNClob()
+	 */
+	public NClob createNClob() {
+	    return new com.mysql.jdbc.NClob();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/ConnectionProperties.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ConnectionProperties.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/ConnectionProperties.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -1430,6 +1430,44 @@
 
 	private BooleanConnectionProperty dumpMetadataOnColumnNotFound = new
BooleanConnectionProperty("dumpMetadataOnColumnNotFound", false, "Should the driver dump
the field-level metadata of a result set into " + "the exception message when
ResultSet.findColumn() fails?", "3.1.13", DEBUGING_PROFILING_CATEGORY,
Integer.MIN_VALUE);
 
+	// SSL Options
+	
+	private StringConnectionProperty clientCertificateKeyStoreUrl = new
StringConnectionProperty(
+			"clientCertificateKeyStoreUrl", null,
+			"URL to the client certificate KeyStore (if not specified, use defaults)", "5.1.0",
+			SECURITY_CATEGORY, Integer.MAX_VALUE);
+	
+	private StringConnectionProperty trustCertificateKeyStoreUrl = new
StringConnectionProperty(
+			"trustCertificateKeyStoreUrl", null,
+			"URL to the trusted root certificate KeyStore (if not specified, use defaults)",
"5.1.0",
+			SECURITY_CATEGORY, Integer.MAX_VALUE);
+	
+	private StringConnectionProperty clientCertificateKeyStoreType = new
StringConnectionProperty(
+			"clientCertificateKeyStoreType", null,
+			"KeyStore type for client certificates (NULL or empty means use default, "
+			+ " standard keystore types supported by the JVM are \"JKS\" and \"PKCS12\", your "
+			+ "environment may have more available depending on what security products are "
+			+ "installed and available to the JVM.", "5.1.0",
+			SECURITY_CATEGORY, Integer.MAX_VALUE);
+	
+	private StringConnectionProperty clientCertificateKeyStorePassword = new
StringConnectionProperty(
+			"clientCertificateKeyStorePassword", null,
+			"Password for the client certificates KeyStore", "5.1.0",
+			SECURITY_CATEGORY, Integer.MAX_VALUE);
+	
+	private StringConnectionProperty trustCertificateKeyStoreType = new
StringConnectionProperty(
+			"trustCertificateKeyStoreType", null,
+			"KeyStore type for trusted root certificates (NULL or empty means use default, "
+			+ " standard keystore types supported by the JVM are \"JKS\" and \"PKCS12\", your "
+			+ "environment may have more available depending on what security products are "
+			+ "installed and available to the JVM.", "5.1.0",
+			SECURITY_CATEGORY, Integer.MAX_VALUE);
+	
+	private StringConnectionProperty trustCertificateKeyStorePassword = new
StringConnectionProperty(
+			"trustCertificateKeyStorePassword", null,
+			"Password for the trusted root certificates KeyStore", "5.1.0",
+			SECURITY_CATEGORY, Integer.MAX_VALUE);
+	
 	protected DriverPropertyInfo[] exposeAsDriverPropertyInfoInternal(
 			Properties info, int slotsToReserve) throws SQLException {
 		initializeProperties(info);
@@ -3720,4 +3758,58 @@
 	public void setUseOldAliasMetadataBehavior(boolean flag) {
 		this.useOldAliasMetadataBehavior.setValue(flag);
 	}
+
+	public String getClientCertificateKeyStorePassword() {
+		return clientCertificateKeyStorePassword.getValueAsString();
+	}
+
+	public void setClientCertificateKeyStorePassword(
+			String value) {
+		this.clientCertificateKeyStorePassword.setValue(value);
+	}
+
+	public String getClientCertificateKeyStoreType() {
+		return clientCertificateKeyStoreType.getValueAsString();
+	}
+
+	public void setClientCertificateKeyStoreType(
+			String value) {
+		this.clientCertificateKeyStoreType.setValue(value);
+	}
+
+	public String getClientCertificateKeyStoreUrl() {
+		return clientCertificateKeyStoreUrl.getValueAsString();
+	}
+
+	public void setClientCertificateKeyStoreUrl(
+			String value) {
+		this.clientCertificateKeyStoreUrl.setValue(value);
+	}
+
+	public String getTrustCertificateKeyStorePassword() {
+		return trustCertificateKeyStorePassword.getValueAsString();
+	}
+
+	public void setTrustCertificateKeyStorePassword(
+			String value) {
+		this.trustCertificateKeyStorePassword.setValue(value);
+	}
+
+	public String getTrustCertificateKeyStoreType() {
+		return trustCertificateKeyStoreType.getValueAsString();
+	}
+
+	public void setTrustCertificateKeyStoreType(
+			String value) {
+		this.trustCertificateKeyStoreType.setValue(value);
+	}
+
+	public String getTrustCertificateKeyStoreUrl() {
+		return trustCertificateKeyStoreUrl.getValueAsString();
+	}
+
+	public void setTrustCertificateKeyStoreUrl(
+			String value) {
+		this.trustCertificateKeyStoreUrl.setValue(value);
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -27,6 +27,7 @@
 import java.io.UnsupportedEncodingException;
 
 import java.sql.ResultSet;
+import java.sql.RowIdLifetime;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Types;
@@ -41,6 +42,8 @@
 import java.util.StringTokenizer;
 import java.util.TreeMap;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
 /**
  * JDBC Interface to Mysql functions
  * <p>
@@ -7362,4 +7365,44 @@
 	public boolean usesLocalFiles() throws SQLException {
 		return false;
 	}
+
+	public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
+		return false;
+	}
+
+	public ResultSet getClientInfoProperties() throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public ResultSet getFunctionParameters(String catalog, String schemaPattern, String
functionNamePattern, String parameterNamePattern) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public ResultSet getFunctions(String catalog, String schemaPattern, String
functionNamePattern) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public RowIdLifetime getRowIdLifetime() throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public boolean providesQueryObjectGenerator() throws SQLException {
+		return false; // we don't - rely on the built-in JDK one
+	}
+
+	public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
+		return true;
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/EscapeProcessor.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/EscapeProcessor.java	2006-09-19 01:45:03 UTC (rev
5748)
+++ trunk/connector-j/src/com/mysql/jdbc/EscapeProcessor.java	2006-09-19 01:47:23 UTC (rev
5749)
@@ -448,11 +448,11 @@
 							"{?=call")) {
 							callingStoredFunction = true;
 							newSql.append("SELECT ");
-							newSql.append(token, startPos, endPos);
+							newSql.append(token.substring(startPos, endPos));
 						} else {
 							callingStoredFunction = false;
 							newSql.append("CALL ");
-							newSql.append(token, startPos, endPos);
+							newSql.append(token.substring(startPos, endPos));
 						}
 
 						for (int i = endPos - 1; i >= startPos; i--) {

Modified: trunk/connector-j/src/com/mysql/jdbc/ExportControlled.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ExportControlled.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/ExportControlled.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -27,7 +27,21 @@
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.sql.SQLException;
 
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+
 /**
  * Holds functionality that falls under export-control regulations.
  * 
@@ -37,6 +51,8 @@
  *          Exp $
  */
 public class ExportControlled {
+	private static final String SQL_STATE_BAD_SSL_PARAMS = "08000";
+
 	protected static boolean enabled() {
 		// we may wish to un-static-ify this class
 		// this static method call may be removed entirely by the compiler
@@ -57,9 +73,8 @@
 	 *             perform the handshake.
 	 */
 	protected static void transformSocketToSSLSocket(MysqlIO mysqlIO)
-			throws CommunicationsException {
-		javax.net.ssl.SSLSocketFactory sslFact = (javax.net.ssl.SSLSocketFactory)
javax.net.ssl.SSLSocketFactory
-				.getDefault();
+			throws SQLException {
+		javax.net.ssl.SSLSocketFactory sslFact =
getSSLSocketFactoryDefaultOrConfigured(mysqlIO);
 
 		try {
 			mysqlIO.mysqlConnection = sslFact.createSocket(
@@ -91,4 +106,128 @@
 
 	private ExportControlled() { /* prevent instantiation */
 	}
+
+	private static SSLSocketFactory getSSLSocketFactoryDefaultOrConfigured(
+			MysqlIO mysqlIO) throws SQLException {
+		String clientCertificateKeyStoreUrl = mysqlIO.connection
+				.getClientCertificateKeyStoreUrl();
+		String trustCertificateKeyStoreUrl = mysqlIO.connection
+				.getTrustCertificateKeyStoreUrl();
+		String clientCertificateKeyStoreType = mysqlIO.connection
+				.getClientCertificateKeyStoreType();
+		String clientCertificateKeyStorePassword = mysqlIO.connection
+				.getClientCertificateKeyStorePassword();
+		String trustCertificateKeyStoreType = mysqlIO.connection
+				.getTrustCertificateKeyStoreType();
+		String trustCertificateKeyStorePassword = mysqlIO.connection
+				.getTrustCertificateKeyStorePassword();
+
+		if (StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)
+				&& StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) {
+			return (javax.net.ssl.SSLSocketFactory) javax.net.ssl.SSLSocketFactory
+					.getDefault();
+		}
+
+		TrustManagerFactory tmf = null;
+		KeyManagerFactory kmf = null;
+
+		try {
+			tmf = TrustManagerFactory.getInstance(TrustManagerFactory
+					.getDefaultAlgorithm());
+			kmf = KeyManagerFactory.getInstance(KeyManagerFactory
+					.getDefaultAlgorithm());
+		} catch (NoSuchAlgorithmException nsae) {
+			throw SQLError
+					.createSQLException(
+							"Default algorithm definitions for TrustManager and/or KeyManager are invalid. 
Check java security properties file.",
+							SQL_STATE_BAD_SSL_PARAMS, 0, false);
+		}
+
+		if (StringUtils.isNullOrEmpty(clientCertificateKeyStoreUrl)) {
+			try {
+				KeyStore clientKeyStore = KeyStore
+						.getInstance(clientCertificateKeyStoreType);
+				URL ksURL = new URL(clientCertificateKeyStoreUrl);
+				char[] password = (clientCertificateKeyStorePassword == null) ? new char[0]
+						: clientCertificateKeyStorePassword.toCharArray();
+				clientKeyStore.load(ksURL.openStream(), password);
+				kmf.init(clientKeyStore, password);
+			} catch (UnrecoverableKeyException uke) {
+				throw SQLError
+						.createSQLException(
+								"Could not recover keys from client keystore.  Check password?",
+								SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			} catch (NoSuchAlgorithmException nsae) {
+				throw SQLError.createSQLException(
+						"Unsupported keystore algorithm [" + nsae.getMessage()
+								+ "]", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			} catch (KeyStoreException kse) {
+				throw SQLError.createSQLException(
+						"Could not create KeyStore instance ["
+								+ kse.getMessage() + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			} catch (CertificateException nsae) {
+				throw SQLError.createSQLException("Could not load client"
+						+ clientCertificateKeyStoreType + " keystore from "
+						+ clientCertificateKeyStoreUrl);
+			} catch (MalformedURLException mue) {
+				throw SQLError.createSQLException(clientCertificateKeyStoreUrl
+						+ " does not appear to be a valid URL.", SQL_STATE_BAD_SSL_PARAMS, 0,
+						false);
+			} catch (IOException ioe) {
+				throw SQLError.createSQLException("Cannot open "
+						+ clientCertificateKeyStoreUrl + " ["
+						+ ioe.getMessage() + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			}
+		}
+
+		if (StringUtils.isNullOrEmpty(trustCertificateKeyStoreUrl)) {
+
+			try {
+				KeyStore trustKeyStore = KeyStore
+						.getInstance(trustCertificateKeyStoreType);
+				URL ksURL = new URL(trustCertificateKeyStoreUrl);
+
+				char[] password = (trustCertificateKeyStorePassword == null) ? new char[0]
+						: trustCertificateKeyStorePassword.toCharArray();
+				trustKeyStore.load(ksURL.openStream(), password);
+				tmf.init(trustKeyStore);
+			} catch (NoSuchAlgorithmException nsae) {
+				throw SQLError.createSQLException(
+						"Unsupported keystore algorithm [" + nsae.getMessage()
+								+ "]", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			} catch (KeyStoreException kse) {
+				throw SQLError.createSQLException(
+						"Could not create KeyStore instance ["
+								+ kse.getMessage() + "]", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			} catch (CertificateException nsae) {
+				throw SQLError.createSQLException("Could not load trust"
+						+ trustCertificateKeyStoreType + " keystore from "
+						+ trustCertificateKeyStoreUrl, SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			} catch (MalformedURLException mue) {
+				throw SQLError.createSQLException(trustCertificateKeyStoreUrl
+						+ " does not appear to be a valid URL.", SQL_STATE_BAD_SSL_PARAMS, 0,
+						false);
+			} catch (IOException ioe) {
+				throw SQLError.createSQLException("Cannot open "
+						+ trustCertificateKeyStoreUrl + " [" + ioe.getMessage()
+						+ "]", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+			}
+		}
+
+		SSLContext sslContext = null;
+
+		try {
+			sslContext = SSLContext.getInstance("TLS");
+			sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+			return sslContext.getSocketFactory();
+		} catch (NoSuchAlgorithmException nsae) {
+			throw SQLError.createSQLException("TLS"
+					+ " is not a valid SSL protocol.", SQL_STATE_BAD_SSL_PARAMS, 0, false);
+		} catch (KeyManagementException kme) {
+			throw SQLError.createSQLException("KeyManagementException: "
+					+ kme.getMessage(), SQL_STATE_BAD_SSL_PARAMS, 0, false);
+		}
+	}
+
 }
\ No newline at end of file

Modified: trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java	2006-09-19 01:45:03
UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/MysqlParameterMetadata.java	2006-09-19 01:47:23
UTC (rev 5749)
@@ -26,6 +26,8 @@
 import java.sql.ParameterMetaData;
 import java.sql.SQLException;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
 public class MysqlParameterMetadata implements ParameterMetaData {
 	
 	ResultSetMetaData metadata = null;
@@ -95,4 +97,12 @@
 	public int getParameterMode(int arg0) throws SQLException {
 		return parameterModeIn;
 	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Added: trunk/connector-j/src/com/mysql/jdbc/MysqlSQLXML.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/MysqlSQLXML.java	2006-09-19 01:45:03 UTC (rev
5748)
+++ trunk/connector-j/src/com/mysql/jdbc/MysqlSQLXML.java	2006-09-19 01:47:23 UTC (rev
5749)
@@ -0,0 +1,542 @@
+package com.mysql.jdbc;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLXML;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXResult;
+import javax.xml.transform.stax.StAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
+public class MysqlSQLXML implements SQLXML, WriterWatcher, OutputStreamWatcher {
+
+	private XMLInputFactory inputFactory;
+
+	private XMLOutputFactory outputFactory;
+
+	private String stringRep;
+
+	private ResultSet owningResultSet;
+
+	private int columnIndexOfXml;
+
+	private boolean fromResultSet;
+
+	private boolean isClosed = false;
+
+	private boolean workingWithResult;
+
+	private DOMResult asDOMResult;
+
+	protected MysqlSQLXML(ResultSet owner, int index) {
+		this.owningResultSet = owner;
+		this.columnIndexOfXml = index;
+		this.fromResultSet = true;
+	}
+
+	protected MysqlSQLXML() {
+		this.fromResultSet = false;
+	}
+
+	public synchronized void free() throws SQLException {
+		this.inputFactory = null;
+		this.outputFactory = null;
+		this.owningResultSet = null;
+		this.workingWithResult = false;
+		this.isClosed = true;
+		
+	}
+
+	public synchronized String getString() throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		if (this.fromResultSet) {
+			return this.owningResultSet.getString(this.columnIndexOfXml);
+		}
+		
+		return this.stringRep;
+	}
+
+	private synchronized void checkClosed() throws SQLException {
+		if (this.isClosed) {
+			throw SQLError.createSQLException("SQLXMLInstance has been free()d");
+		}
+	}
+
+	private synchronized void checkWorkingWithResult() throws SQLException {
+		if (this.workingWithResult) {
+			throw SQLError.createSQLException("Can't perform requested operation after getResult()
has been called to write XML data",
+					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		}
+	}
+
+	/**
+	 * Sets the XML value designated by this SQLXML instance to the given String
+	 * representation. The format of this String is defined by
+	 * org.xml.sax.InputSource, where the characters in the stream represent the
+	 * unicode code points for XML according to section 2 and appendix B of the
+	 * XML 1.0 specification. Although an encoding declaration other than
+	 * unicode may be present, the encoding of the String is unicode. The
+	 * behavior of this method is the same as ResultSet.updateString() when the
+	 * designated column of the ResultSet has a type java.sql.Types of SQLXML.
+	 * <p>
+	 * The SQL XML object becomes not writeable when this method is called and
+	 * may also become not readable depending on implementation.
+	 * 
+	 * @param value
+	 *            the XML value
+	 * @throws SQLException
+	 *             if there is an error processing the XML value. The getCause()
+	 *             method of the exception may provide a more detailed
+	 *             exception, for example, if the stream does not contain valid
+	 *             characters. An exception is thrown if the state is not
+	 *             writable.
+	 * @exception SQLFeatureNotSupportedException
+	 *                if the JDBC driver does not support this method
+	 * @since 1.6
+	 */
+
+	public synchronized void setString(String str) throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		this.stringRep = str;
+		this.fromResultSet = false;
+	}
+
+	public synchronized boolean isEmpty() throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		if (!this.fromResultSet) {
+			return this.stringRep == null || this.stringRep.length() == 0;
+		}
+		
+		return false;
+	}
+
+	public synchronized InputStream getBinaryStream() throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		return this.owningResultSet.getBinaryStream(this.columnIndexOfXml);
+	}
+
+	/**
+	 * Retrieves the XML value designated by this SQLXML instance as a
+	 * java.io.Reader object. The format of this stream is defined by
+	 * org.xml.sax.InputSource, where the characters in the stream represent the
+	 * unicode code points for XML according to section 2 and appendix B of the
+	 * XML 1.0 specification. Although an encoding declaration other than
+	 * unicode may be present, the encoding of the stream is unicode. The
+	 * behavior of this method is the same as ResultSet.getCharacterStream()
+	 * when the designated column of the ResultSet has a type java.sql.Types of
+	 * SQLXML.
+	 * <p>
+	 * The SQL XML object becomes not readable when this method is called and
+	 * may also become not writable depending on implementation.
+	 * 
+	 * @return a stream containing the XML data.
+	 * @throws SQLException
+	 *             if there is an error processing the XML value. The getCause()
+	 *             method of the exception may provide a more detailed
+	 *             exception, for example, if the stream does not contain valid
+	 *             characters. An exception is thrown if the state is not
+	 *             readable.
+	 * @exception SQLFeatureNotSupportedException
+	 *                if the JDBC driver does not support this method
+	 * @since 1.6
+	 */
+	public synchronized Reader getCharacterStream() throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		return this.owningResultSet.getCharacterStream(this.columnIndexOfXml);
+	}
+
+	/**
+	 * Returns a Source for reading the XML value designated by this SQLXML
+	 * instance. Sources are used as inputs to XML parsers and XSLT
+	 * transformers.
+	 * <p>
+	 * Sources for XML parsers will have namespace processing on by default. The
+	 * systemID of the Source is implementation dependent.
+	 * <p>
+	 * The SQL XML object becomes not readable when this method is called and
+	 * may also become not writable depending on implementation.
+	 * <p>
+	 * Note that SAX is a callback architecture, so a returned SAXSource should
+	 * then be set with a content handler that will receive the SAX events from
+	 * parsing. The content handler will receive callbacks based on the contents
+	 * of the XML.
+	 * 
+	 * <pre>
+	 * SAXSource saxSource = sqlxml.getSource(SAXSource.class);
+	 * XMLReader xmlReader = saxSource.getXMLReader();
+	 * xmlReader.setContentHandler(myHandler);
+	 * xmlReader.parse(saxSource.getInputSource());
+	 * </pre>
+	 * 
+	 * @param sourceClass
+	 *            The class of the source, or null. If the class is null, a
+	 *            vendor specifc Source implementation will be returned. The
+	 *            following classes are supported at a minimum:
+	 *            
+	 *            (MySQL returns a SAXSource if sourceClass == null)
+	 * 
+	 * <pre>
+	 *    javax.xml.transform.dom.DOMSource - returns a DOMSource
+	 *    javax.xml.transform.sax.SAXSource - returns a SAXSource
+	 *    javax.xml.transform.stax.StAXSource - returns a StAXSource
+	 *    javax.xml.transform.stream.StreamSource - returns a StreamSource
+	 * </pre>
+	 * 
+	 * @return a Source for reading the XML value.
+	 * @throws SQLException
+	 *             if there is an error processing the XML value or if this
+	 *             feature is not supported. The getCause() method of the
+	 *             exception may provide a more detailed exception, for example,
+	 *             if an XML parser exception occurs. An exception is thrown if
+	 *             the state is not readable.
+	 * @exception SQLFeatureNotSupportedException
+	 *                if the JDBC driver does not support this method
+	 * @since 1.6
+	 */
+	public synchronized Source getSource(Class clazz) throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		// Note that we try and use streams here wherever possible
+		// for the day that the server actually supports streaming
+		// from server -> client (futureproofing)
+
+		if (clazz == null || clazz.equals(SAXSource.class)) {
+			
+			InputSource inputSource = null;
+			
+			if (this.fromResultSet) {
+				inputSource = new InputSource(
+						this.owningResultSet
+						.getCharacterStream(this.columnIndexOfXml));
+			} else {
+				inputSource = new InputSource(new StringReader(this.stringRep));
+			}
+			
+			return new SAXSource(inputSource);
+		} else if (clazz.equals(DOMSource.class)) {
+			try {
+				DocumentBuilderFactory builderFactory = DocumentBuilderFactory
+						.newInstance();
+				builderFactory.setNamespaceAware(true);
+				DocumentBuilder builder = builderFactory.newDocumentBuilder();
+
+				InputSource inputSource = null;
+				
+				if (this.fromResultSet) {
+					inputSource = new InputSource(
+							this.owningResultSet
+							.getCharacterStream(this.columnIndexOfXml));
+				} else {
+					inputSource = new InputSource(new StringReader(this.stringRep));
+				}
+
+				return new DOMSource(builder.parse(inputSource));
+			} catch (Throwable t) {
+				// FIXME - need to use factory method and set cause here
+
+				throw new SQLException(t);
+			}
+
+		} else if (clazz.equals(StreamSource.class)) {
+			Reader reader = null;
+			
+			if (this.fromResultSet) {
+				reader = this.owningResultSet
+							.getCharacterStream(this.columnIndexOfXml);
+			} else {
+				reader = new StringReader(this.stringRep);
+			}
+			
+			return new StreamSource(reader);
+		} else if (clazz.equals(StAXSource.class)) {
+			try {
+				Reader reader = null;
+				
+				if (this.fromResultSet) {
+					reader = this.owningResultSet
+								.getCharacterStream(this.columnIndexOfXml);
+				} else {
+					reader = new StringReader(this.stringRep);
+				}
+				
+				return new StAXSource(this.inputFactory
+						.createXMLStreamReader(reader));
+			} catch (XMLStreamException ex) {
+				SQLException sqlEx = SQLError.createSQLException(ex
+						.getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				// perhaps setCause here w/ ex?
+				throw sqlEx;
+			}
+		} else {
+			throw SQLError.createSQLException("XML Source of type \""
+					+ clazz.toString() + "\" Not supported.",
+					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		}
+	}
+
+	/**
+	 * Retrieves a stream that can be used to write the XML value that this
+	 * SQLXML instance represents. The stream begins at position 0. The bytes of
+	 * the stream are interpreted according to appendix F of the XML 1.0
+	 * specification The behavior of this method is the same as
+	 * ResultSet.updateBinaryStream() when the designated column of the
+	 * ResultSet has a type java.sql.Types of SQLXML.
+	 * <p>
+	 * The SQL XML object becomes not writeable when this method is called and
+	 * may also become not readable depending on implementation.
+	 * 
+	 * @return a stream to which data can be written.
+	 * @throws SQLException
+	 *             if there is an error processing the XML value. An exception
+	 *             is thrown if the state is not writable.
+	 * @exception SQLFeatureNotSupportedException
+	 *                if the JDBC driver does not support this method
+	 * @since 1.6
+	 */
+	public synchronized OutputStream setBinaryStream() throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		this.workingWithResult = true;
+		
+		return setBinaryStreamInternal();
+	}
+
+	private OutputStream setBinaryStreamInternal() throws SQLException {
+		WatchableOutputStream bytesOut = new WatchableOutputStream();
+		bytesOut.setWatcher(this);
+
+		return bytesOut;
+	}
+	
+	/**
+	 * Retrieves a stream to be used to write the XML value that this SQLXML
+	 * instance represents. The format of this stream is defined by
+	 * org.xml.sax.InputSource, where the characters in the stream represent the
+	 * unicode code points for XML according to section 2 and appendix B of the
+	 * XML 1.0 specification. Although an encoding declaration other than
+	 * unicode may be present, the encoding of the stream is unicode. The
+	 * behavior of this method is the same as ResultSet.updateCharacterStream()
+	 * when the designated column of the ResultSet has a type java.sql.Types of
+	 * SQLXML.
+	 * <p>
+	 * The SQL XML object becomes not writeable when this method is called and
+	 * may also become not readable depending on implementation.
+	 * 
+	 * @return a stream to which data can be written.
+	 * @throws SQLException
+	 *             if there is an error processing the XML value. The getCause()
+	 *             method of the exception may provide a more detailed
+	 *             exception, for example, if the stream does not contain valid
+	 *             characters. An exception is thrown if the state is not
+	 *             writable.
+	 * @exception SQLFeatureNotSupportedException
+	 *                if the JDBC driver does not support this method
+	 * @since 1.6
+	 */
+	public synchronized Writer setCharacterStream() throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		this.workingWithResult = true;
+		
+		return setCharacterStreamInternal();
+	}
+
+	private Writer setCharacterStreamInternal() throws SQLException {
+		WatchableWriter writer = new WatchableWriter();
+		writer.setWatcher(this);
+
+		return writer;
+	}
+	
+	/**
+	 * Returns a Result for setting the XML value designated by this SQLXML
+	 * instance.
+	 * <p>
+	 * The systemID of the Result is implementation dependent.
+	 * <p>
+	 * The SQL XML object becomes not writeable when this method is called and
+	 * may also become not readable depending on implementation.
+	 * <p>
+	 * Note that SAX is a callback architecture and the returned SAXResult has a
+	 * content handler assigned that will receive the SAX events based on the
+	 * contents of the XML. Call the content handler with the contents of the
+	 * XML document to assign the values.
+	 * 
+	 * <pre>
+	 * SAXResult saxResult = sqlxml.setResult(SAXResult.class);
+	 * ContentHandler contentHandler = saxResult.getXMLReader().getContentHandler();
+	 * contentHandler.startDocument();
+	 * // set the XML elements and attributes into the result
+	 * contentHandler.endDocument();
+	 * </pre>
+	 * 
+	 * @param resultClass
+	 *            The class of the result, or null. If resultClass is null, a
+	 *            vendor specific Result implementation will be returned. The
+	 *            following classes are supported at a minimum:
+	 * 
+	 * <pre>
+	 *    javax.xml.transform.dom.DOMResult - returns a DOMResult
+	 *    javax.xml.transform.sax.SAXResult - returns a SAXResult
+	 *    javax.xml.transform.stax.StAXResult - returns a StAXResult
+	 *    javax.xml.transform.stream.StreamResult - returns a StreamResult
+	 * </pre>
+	 * 
+	 * @return Returns a Result for setting the XML value.
+	 * @throws SQLException
+	 *             if there is an error processing the XML value or if this
+	 *             feature is not supported. The getCause() method of the
+	 *             exception may provide a more detailed exception, for example,
+	 *             if an XML parser exception occurs. An exception is thrown if
+	 *             the state is not writable.
+	 * @exception SQLFeatureNotSupportedException
+	 *                if the JDBC driver does not support this method
+	 * @since 1.6
+	 */
+	public synchronized Result setResult(Class clazz) throws SQLException {
+		checkClosed();
+		checkWorkingWithResult();
+		
+		this.workingWithResult = true;
+		this.asDOMResult = null;
+		this.stringRep = null;
+		
+		if (clazz == null || clazz.equals(SAXResult.class)) {
+			
+			// TODO: Need to flesh this out
+			return new SAXResult(null);
+		} else if (clazz.equals(DOMResult.class)) {
+			
+			this.asDOMResult = new DOMResult();
+			return this.asDOMResult;
+
+		} else if (clazz.equals(StreamResult.class)) {
+			return new StreamResult(setCharacterStreamInternal());
+		} else if (clazz.equals(StAXResult.class)) {
+			try {
+				return new StAXResult(this.outputFactory.createXMLEventWriter(
+						setCharacterStreamInternal()));
+			} catch (XMLStreamException ex) {
+				SQLException sqlEx = SQLError.createSQLException(ex
+						.getMessage(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				// perhaps setCause here w/ ex?
+				throw sqlEx;
+			}
+		} else {
+			throw SQLError.createSQLException("XML Result of type \""
+					+ clazz.toString() + "\" Not supported.",
+					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		}
+	}
+
+	/**
+	 * @see com.mysql.jdbc.WriterWatcher#writerClosed(char[])
+	 */
+	public void writerClosed(WatchableWriter out) {
+		try {
+			setString(out.toString());
+		} catch (SQLException sqlEx) {
+			// never actually thrown in our impl
+		}
+	}
+
+	public void streamClosed(WatchableOutputStream out) {
+		
+		try {
+			// There's got to be an easier way to do this, but
+			// I don't feel like coding up Appendix F of the XML Spec
+			// myself, when there's a reusable way to do it, and we
+			// can warn folks away from BINARY xml streams that have
+			// to be parsed to determine the character encoding :P
+			
+			String encoding = "UTF-8";
+
+			try {
+				ByteArrayInputStream bIn = new ByteArrayInputStream(out.toByteArray());
+				XMLStreamReader reader = this.inputFactory.createXMLStreamReader(bIn);
+
+				int eventType = 0;
+
+				while ((eventType = reader.next()) != XMLStreamReader.END_DOCUMENT) {
+					if (eventType == XMLStreamReader.START_DOCUMENT) {
+						String possibleEncoding = reader.getEncoding();
+
+						if (possibleEncoding != null) {
+							encoding = possibleEncoding;
+						}
+
+						break;
+					}
+				}
+			} catch (Throwable t) {
+				// ignore, dealt with later when the string can't be parsed
+				// into valid XML
+			}
+
+			setString(new String(out.toByteArray(), encoding));
+		} catch (UnsupportedEncodingException badEnc) {
+			throw new RuntimeException(badEnc);
+		} catch (SQLException sqlEx) {
+			// never actually thrown in our impl
+		}
+	}
+	
+	protected synchronized String serializeAsString() throws SQLException {
+		checkClosed();
+		if (this.workingWithResult) {
+			// figure out what kind of result
+			if (this.stringRep != null) {
+				return this.stringRep;
+			}
+			
+			if (this.asDOMResult != null) {
+				// serialize from DOM
+			}
+		}
+		
+		return getString(); 
+	}
+}

Added: trunk/connector-j/src/com/mysql/jdbc/NClob.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/NClob.java	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/NClob.java	2006-09-19 01:47:23 UTC (rev 5749)
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2002-2004 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;
+
+/**
+ * Simplistic implementation of java.sql.NClob for MySQL Connector/J
+ * 
+ * @author Tetsuro Ikeda
+ * @version $Id: NClob.java 4963 2006-02-21 13:28:14Z tikeda $
+ */
+public class NClob extends Clob implements java.sql.NClob {
+
+	NClob() {
+        super();
+    }
+	
+    NClob(String charDataInit) {
+        super(charDataInit);
+    }
+}

Modified: trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -37,9 +37,12 @@
 import java.net.URL;
 import java.sql.Array;
 import java.sql.Clob;
+import java.sql.NClob;
 import java.sql.ParameterMetaData;
 import java.sql.Ref;
+import java.sql.RowId;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
@@ -50,6 +53,7 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 import com.mysql.jdbc.exceptions.MySQLTimeoutException;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
@@ -322,7 +326,7 @@
 	 * @throws IOException
 	 *             DOCUMENT ME!
 	 */
-	private static int readFully(Reader reader, char[] buf, int length)
+	protected static int readFully(Reader reader, char[] buf, int length)
 			throws IOException {
 		int numCharsRead = 0;
 
@@ -1142,11 +1146,11 @@
 		CancelTask timeoutTask = null;
 
 		try {
-			if (this.timeout != 0
+			if (this.timeoutInMillis != 0
 					&& locallyScopedConnection.versionMeetsMinimum(5, 0, 0)) {
 				timeoutTask = new CancelTask();
 				Connection.getCancelTimer().schedule(timeoutTask, 
-						this.timeout);
+						this.timeoutInMillis);
 			}
 			
 			rs = locallyScopedConnection.execSQL(this, null, maxRowsToRetrieve, sendPacket,
@@ -1925,6 +1929,10 @@
 		return this.isNull[paramIndex];
 	}
 
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
 	private final int readblock(InputStream i, byte[] b) throws SQLException {
 		try {
 			return i.read(b);
@@ -2097,6 +2105,11 @@
 		}
 	}
 
+	public void setBlob(int parameterIndex, InputStream inputStream, long length)
+			throws SQLException {
+		setBinaryStream(parameterIndex, inputStream, (int)length);
+	}
+
 	/**
 	 * JDBC 2.0 Set a BLOB parameter.
 	 * 
@@ -2440,6 +2453,11 @@
 		}
 	}
 
+	public void setClob(int parameterIndex, Reader reader, long length)
+			throws SQLException {
+		setCharacterStream(parameterIndex, reader, length);
+	}
+
 	/**
 	 * Set a parameter to a java.sql.Date value. The driver converts this to a
 	 * SQL DATE value when it sends it to the database.
@@ -2605,6 +2623,203 @@
 	}
 
 	/**
+     * JDBC 2.0 When a very large UNICODE value is input to a LONGVARCHAR
+     * parameter, it may be more practical to send it via a java.io.Reader. JDBC
+     * will read the data from the stream as needed, until it reaches
+     * end-of-file. The JDBC driver will do any necessary conversion from
+     * UNICODE to the database char format.
+     * 
+     * <P>
+     * <B>Note:</B> This stream object can either be a standard Java stream
+     * object or your own subclass that implements the standard interface.
+     * </p>
+     * 
+     * @param parameterIndex
+     *            the first parameter is 1, the second is 2, ...
+     * @param reader
+     *            the java reader which contains the UNICODE data
+     * @param length
+     *            the number of characters in the stream
+     * 
+     * @exception SQLException
+     *                if a database-access error occurs.
+     */
+	public void setNCharacterStream(int parameterIndex, Reader reader,
+			long length) throws SQLException {
+        try {
+            if (reader == null) {
+                setNull(parameterIndex, java.sql.Types.LONGNVARCHAR);
+                
+            } else {
+                char[] c = null;
+                int len = 0;
+
+                boolean useLength = this.connection
+                        .getUseStreamLengthsInPrepStmts();
+                
+                // Ignore "clobCharacterEncoding" because utf8 should be used this time.
+
+                if (useLength && (length != -1)) {
+                    c = new char[(int) length];  // can't take more than
Integer.MAX_VALUE
+
+                    int numCharsRead = readFully(reader, c, (int) length); // blocks
+                    // until
+                    // all
+                    // read
+                    setNString(parameterIndex, new String(c, 0, numCharsRead));
+
+                } else {
+                    c = new char[4096];
+
+                    StringBuffer buf = new StringBuffer();
+
+                    while ((len = reader.read(c)) != -1) {
+                        buf.append(c, 0, len);
+                    }
+
+                    setNString(parameterIndex, buf.toString());
+                }
+            }
+        } catch (java.io.IOException ioEx) {
+            throw SQLError.createSQLException(ioEx.toString(),
+                    SQLError.SQL_STATE_GENERAL_ERROR);
+        }
+    }
+    
+    /**
+     * JDBC 4.0 Set a NCLOB parameter.
+     * 
+     * @param i
+     *            the first parameter is 1, the second is 2, ...
+     * @param x
+     *            an object representing a NCLOB
+     * 
+     * @throws SQLException
+     *             if a database error occurs
+     */
+	public void setNClob(int parameterIndex, NClob value) throws SQLException {
+		if (value == null) {
+            setNull(parameterIndex, java.sql.Types.NCLOB);
+        } else {
+            setNCharacterStream(parameterIndex, value.getCharacterStream(),
value.length());
+        }
+	}
+
+    /**
+     * Set a parameter to a Java String value. The driver converts this to a SQL
+     * VARCHAR or LONGVARCHAR value with introducer _utf8 (depending on the 
+     * arguments size relative to the driver's limits on VARCHARs) when it sends 
+     * it to the database. If charset is set as utf8, this method just call setString.
+     * 
+     * @param parameterIndex
+     *            the first parameter is 1...
+     * @param x
+     *            the parameter value
+     * 
+     * @exception SQLException
+     *                if a database access error occurs
+     */
+    public void setNString(int parameterIndex, String x) throws SQLException {
+        if (this.charEncoding.equalsIgnoreCase("UTF-8")
+                || this.charEncoding.equalsIgnoreCase("utf8")) {
+            setString(parameterIndex, x);
+            return;
+        }
+
+        // if the passed string is null, then set this column to null
+        if (x == null) {
+            setNull(parameterIndex, java.sql.Types.NCHAR); 
+        } else {
+            int stringLength = x.length();
+            // Ignore sql_mode=NO_BACKSLASH_ESCAPES in current implementation.
+
+            // Add introducer _utf8 for NATIONAL CHARACTER
+            StringBuffer buf = new StringBuffer((int) (x.length() * 1.1 + 4));
+            buf.append("_utf8");
+            buf.append('\'');
+
+            //
+            // Note: buf.append(char) is _faster_ than
+            // appending in blocks, because the block
+            // append requires a System.arraycopy()....
+            // go figure...
+            //
+
+            for (int i = 0; i < stringLength; ++i) {
+                char c = x.charAt(i);
+
+                switch (c) {
+                case 0: /* Must be escaped for 'mysql' */
+                    buf.append('\\');
+                    buf.append('0');
+
+                    break;
+
+                case '\n': /* Must be escaped for logs */
+                    buf.append('\\');
+                    buf.append('n');
+
+                    break;
+
+                case '\r':
+                    buf.append('\\');
+                    buf.append('r');
+
+                    break;
+
+                case '\\':
+                    buf.append('\\');
+                    buf.append('\\');
+
+                    break;
+
+                case '\'':
+                    buf.append('\\');
+                    buf.append('\'');
+
+                    break;
+
+                case '"': /* Better safe than sorry */
+                    if (this.usingAnsiMode) {
+                        buf.append('\\');
+                    }
+
+                    buf.append('"');
+
+                    break;
+
+                case '\032': /* This gives problems on Win32 */
+                    buf.append('\\');
+                    buf.append('Z');
+
+                    break;
+
+                default:
+                    buf.append(c);
+                }
+            }
+
+            buf.append('\'');
+
+            String parameterAsString = buf.toString();
+
+            byte[] parameterAsBytes = null;
+
+            if (!this.isLoadDataQuery) {
+                parameterAsBytes = StringUtils.getBytes(parameterAsString,
+                        this.connection.getCharsetConverter("UTF-8"), "UTF-8", 
+                                this.connection.getServerCharacterEncoding(),
+                                this.connection.parserKnowsUnicode());
+            } else {
+                // Send with platform character encoding
+                parameterAsBytes = parameterAsString.getBytes();
+            }
+
+            setInternal(parameterIndex, parameterAsBytes);
+        }
+    }
+
+	/**
 	 * Set a parameter to SQL NULL
 	 * 
 	 * <p>
@@ -3143,6 +3358,10 @@
 		this.retrieveGeneratedKeys = retrieveGeneratedKeys;
 	}
 
+	public void setRowId(int parameterIndex, RowId x) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
 	/**
 	 * Sets the value for the placeholder as a serialized Java object (used by
 	 * various forms of setObject()
@@ -3192,6 +3411,19 @@
 		setInternal(parameterIndex, String.valueOf(x));
 	}
 
+	public void setSQLXML(int parameterIndex, SQLXML xmlObject)
+			throws SQLException {
+		if (xmlObject == null) {
+			setNull(parameterIndex, Types.SQLXML);
+		} else {
+			if (xmlObject instanceof MysqlSQLXML) {
+				setString(parameterIndex, ((MysqlSQLXML)xmlObject).serializeAsString());
+			} else {
+				setString(parameterIndex, xmlObject.getString());
+			}
+		}
+	}
+
 	/**
 	 * Set a parameter to a Java String value. The driver converts this to a SQL
 	 * VARCHAR or LONGVARCHAR value (depending on the arguments size relative to
@@ -3750,4 +3982,88 @@
 
 		return buf.toString();
 	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public void setPoolable(boolean poolable) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
+		setAsciiStream(parameterIndex, x, -1);
+		
+	}
+
+	public void setAsciiStream(int parameterIndex, InputStream x, long length) throws
SQLException {
+		setAsciiStream(parameterIndex, x, (int)length);
+		
+	}
+
+	public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
+		setBinaryStream(parameterIndex, x, -1);
+		
+	}
+
+	public void setBinaryStream(int parameterIndex, InputStream x, long length) throws
SQLException {
+		setBinaryStream(parameterIndex, x, (int)length);
+		
+	}
+
+	public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
+		setBinaryStream(parameterIndex, inputStream);
+		
+	}
+
+	public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
+		setCharacterStream(parameterIndex, reader, -1);
+		
+	}
+
+	public void setCharacterStream(int parameterIndex, Reader reader, long length) throws
SQLException {
+		setCharacterStream(parameterIndex, reader, (int)length);
+		
+	}
+
+	public void setClob(int parameterIndex, Reader reader) throws SQLException {
+		setCharacterStream(parameterIndex, reader);
+		
+	}
+
+	public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
+		setNCharacterStream(parameterIndex, value, -1);
+		
+	}
+
+	public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+		setNCharacterStream(parameterIndex, reader);
+		
+	}
+
+	public synchronized boolean isClosed() throws SQLException {
+		return this.isClosed;
+	}
+
+	/**
+	 * JDBC 4.0 Set a NCLOB parameter.
+	 * 
+	 * @param parameterIndex
+	 *            the first parameter is 1, the second is 2, ...
+	 * @param reader
+	 *            the java reader which contains the UNICODE data
+	 * @param length
+	 *            the number of characters in the stream
+	 * 
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void setNClob(int parameterIndex, Reader reader, long length)
+			throws SQLException {
+	    if (reader == null) {
+	        setNull(parameterIndex, java.sql.Types.NCLOB);
+	    } else {
+	        setNCharacterStream(parameterIndex, reader, length);
+	    }
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/ReplicationConnection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ReplicationConnection.java	2006-09-19 01:45:03
UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/ReplicationConnection.java	2006-09-19 01:47:23
UTC (rev 5749)
@@ -21,13 +21,21 @@
  */
 package com.mysql.jdbc;
 
+import java.sql.Array;
+import java.sql.BaseQuery;
+import java.sql.Blob;
 import java.sql.CallableStatement;
+import java.sql.Clob;
 import java.sql.DatabaseMetaData;
+import java.sql.NClob;
 import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
+import java.sql.SQLXML;
 import java.sql.Savepoint;
 import java.sql.Statement;
+import java.sql.Struct;
 import java.util.Map;
 import java.util.Properties;
 
@@ -512,4 +520,66 @@
 		
 		this.currentConnection = switchToConnection;
 	}
+
+	public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+		return this.currentConnection.createArrayOf(typeName, elements);
+	}
+
+	public Blob createBlob() throws SQLException {
+		return this.currentConnection.createBlob();
+	}
+
+	public Clob createClob() throws SQLException {
+		return this.currentConnection.createClob();
+	}
+
+	public NClob createNClob() throws SQLException {
+		return this.currentConnection.createNClob();
+	}
+
+	public BaseQuery createQueryObject(Class arg0) throws SQLException {
+		return this.currentConnection.createQueryObject(arg0);
+	}
+
+	public BaseQuery createQueryObject(Class arg0, java.sql.Connection arg1) throws
SQLException {
+		return this.currentConnection.createQueryObject(arg0, arg1);
+	}
+
+	public SQLXML createSQLXML() throws SQLException {
+		return this.currentConnection.createSQLXML();
+	}
+
+	public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+		return this.currentConnection.createStruct(typeName, attributes);
+	}
+
+	public Properties getClientInfo() throws SQLException {
+		return this.currentConnection.getClientInfo();
+	}
+
+	public String getClientInfo(String name) throws SQLException {
+		return this.currentConnection.getClientInfo(name);
+	}
+
+	public boolean isValid(int timeout) throws SQLException {
+		return this.currentConnection.isValid(timeout);
+	}
+
+	public void setClientInfo(Properties properties) throws SQLClientInfoException {
+		this.masterConnection.setClientInfo(properties);
+		this.slavesConnection.setClientInfo(properties);
+	}
+
+	public void setClientInfo(String name, String value) throws SQLClientInfoException {
+		this.masterConnection.setClientInfo(name, value);
+		this.slavesConnection.setClientInfo(name, value);
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		return this.currentConnection.isWrapperFor(arg0);
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		return this.currentConnection.unwrap(arg0);
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/ResultSet.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ResultSet.java	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/ResultSet.java	2006-09-19 01:47:23 UTC (rev 5749)
@@ -24,6 +24,7 @@
  */
 package com.mysql.jdbc;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 import com.mysql.jdbc.profiler.ProfileEventSink;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
@@ -31,6 +32,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
+import java.io.Reader;
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 
@@ -43,9 +45,12 @@
 import java.sql.Array;
 import java.sql.DataTruncation;
 import java.sql.Date;
+import java.sql.NClob;
 import java.sql.Ref;
+import java.sql.RowId;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
+import java.sql.SQLXML;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
@@ -8454,4 +8459,430 @@
 					SQLError.SQL_STATE_GENERAL_ERROR);
 		}
 	}
+	
+	/**
+	 * JDBC 4.0
+	 * 
+	 * <p>
+	 * Get the value of a column in the current row as a java.io.Reader.
+	 * </p>
+	 * 
+	 * @param columnIndex
+	 *            the column to get the value from
+	 * 
+	 * @return the value in the column as a java.io.Reader.
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	public Reader getNCharacterStream(int columnIndex) throws SQLException {
+		String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet();
+		if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
+			throw new SQLException(
+					"Can not call getNCharacterStream() when field's charset isn't UTF-8");
+		}
+		return getCharacterStream(columnIndex);
+	}
+
+	/**
+	 * JDBC 4.0
+	 * 
+	 * <p>
+	 * Get the value of a column in the current row as a java.io.Reader.
+	 * </p>
+	 * 
+	 * @param columnName
+	 *            the column name to retrieve the value from
+	 * 
+	 * @return the value as a java.io.Reader
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	public Reader getNCharacterStream(String columnName) throws SQLException {
+		return getNCharacterStream(findColumn(columnName));
+	}
+
+	/**
+	 * JDBC 4.0 Get a NCLOB column.
+	 * 
+	 * @param i
+	 *            the first column is 1, the second is 2, ...
+	 * 
+	 * @return an object representing a NCLOB
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	public NClob getNClob(int columnIndex) throws SQLException {
+		String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet();
+		if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
+			throw new SQLException(
+					"Can not call getNClob() when field's charset isn't UTF-8");
+		}
+		if (!this.isBinaryEncoded) {
+			String asString = getStringForNClob(columnIndex);
+
+			if (asString == null) {
+				return null;
+			}
+
+			return new com.mysql.jdbc.NClob(asString);
+		}
+
+		return getNativeNClob(columnIndex);
+	}
+
+	/**
+	 * JDBC 4.0 Get a NCLOB column.
+	 * 
+	 * @param colName
+	 *            the column name
+	 * 
+	 * @return an object representing a NCLOB
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	public NClob getNClob(String columnName) throws SQLException {
+		return getNClob(findColumn(columnName));
+	}
+	
+	/**
+	 * JDBC 4.0 Get a NCLOB column.
+	 * 
+	 * @param columnIndex
+	 *            the first column is 1, the second is 2, ...
+	 * 
+	 * @return an object representing a NCLOB
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	protected java.sql.NClob getNativeNClob(int columnIndex)
+			throws SQLException {
+		String stringVal = getStringForNClob(columnIndex);
+
+		if (stringVal == null) {
+			return null;
+		}
+
+		return getNClobFromString(stringVal, columnIndex);
+	}
+	
+	private String getStringForNClob(int columnIndex) throws SQLException {
+		String asString = null;
+
+		String forcedEncoding = "UTF-8";
+
+		try {
+			byte[] asBytes = null;
+
+			if (!this.isBinaryEncoded) {
+				asBytes = getBytes(columnIndex);
+			} else {
+				asBytes = getNativeBytes(columnIndex, true);
+			}
+
+			if (asBytes != null) {
+				asString = new String(asBytes, forcedEncoding);
+			}
+		} catch (UnsupportedEncodingException uee) {
+			throw SQLError.createSQLException("Unsupported character encoding "
+					+ forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		}
+
+		return asString;
+	}
+	
+	private final java.sql.NClob getNClobFromString(String stringVal,
+			int columnIndex) throws SQLException {
+		return new com.mysql.jdbc.NClob(stringVal);
+	}
+	
+	/**
+	 * JDBC 4.0
+	 * 
+	 * Get the value of a column in the current row as a Java String
+	 * 
+	 * @param columnIndex
+	 *            the first column is 1, the second is 2...
+	 * 
+	 * @return the column value, null for SQL NULL
+	 * 
+	 * @exception SQLException
+	 *                if a database access error occurs
+	 */
+	public String getNString(int columnIndex) throws SQLException {
+		String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet();
+		if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
+			throw new SQLException(
+					"Can not call getNString() when field's charset isn't UTF-8");
+		}
+		return getString(columnIndex);
+	}
+	
+	/**
+	 * JDBC 4.0
+	 * 
+	 * The following routines simply convert the columnName into a columnIndex
+	 * and then call the appropriate routine above.
+	 * 
+	 * @param columnName
+	 *            is the SQL name of the column
+	 * 
+	 * @return the column value
+	 * 
+	 * @exception SQLException
+	 *                if a database access error occurs
+	 */
+	public String getNString(String columnName) throws SQLException {
+		return getNString(findColumn(columnName));
+	}
+	
+	/**
+	 * JDBC 4.0 Update a column with a character stream value. The updateXXX()
+	 * methods are used to update column values in the current row, or the
+	 * insert row. The updateXXX() methods do not update the underlying
+	 * database, instead the updateRow() or insertRow() methods are called to
+	 * update the database.
+	 * 
+	 * @param columnIndex
+	 *            the first column is 1, the second is 2, ...
+	 * @param x
+	 *            the new column value
+	 * @param length
+	 *            the length of the stream
+	 * 
+	 * @exception SQLException
+	 *                if a database-access error occurs
+	 * @throws NotUpdatable
+	 *             DOCUMENT ME!
+	 */
+	public void updateNCharacterStream(int columnIndex, Reader x, int length)
+			throws SQLException {
+		throw new NotUpdatable();
+	}
+
+	/**
+	 * JDBC 4.0 Update a column with a character stream value. The updateXXX()
+	 * methods are used to update column values in the current row, or the
+	 * insert row. The updateXXX() methods do not update the underlying
+	 * database, instead the updateRow() or insertRow() methods are called to
+	 * update the database.
+	 * 
+	 * @param columnName
+	 *            the name of the column
+	 * @param reader
+	 *            the stream to update the column with
+	 * @param length
+	 *            of the stream
+	 * 
+	 * @throws SQLException
+	 *             if a database-access error occurs
+	 */
+	public void updateNCharacterStream(String columnName, Reader reader,
+			int length) throws SQLException {
+		updateNCharacterStream(findColumn(columnName), reader, length);
+	}
+	
+
+
+	/**
+	 * @see ResultSet#updateNClob(String, NClob)
+	 */
+	public void updateNClob(String columnName, NClob nClob) throws SQLException {
+		updateNClob(findColumn(columnName), nClob);
+	}
+	
+	public void updateRowId(int columnIndex, RowId x) throws SQLException {
+		throw new NotUpdatable();
+	}
+
+	public void updateRowId(String columnName, RowId x) throws SQLException {
+		updateRowId(findColumn(columnName), x);
+	}
+
+	public int getHoldability() throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public RowId getRowId(int columnIndex) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public RowId getRowId(String columnLabel) throws SQLException {
+		return getRowId(findColumn(columnLabel));
+	}
+
+	public SQLXML getSQLXML(int columnIndex) throws SQLException {
+		return new MysqlSQLXML(this, columnIndex);
+	}
+
+	public SQLXML getSQLXML(String columnLabel) throws SQLException {
+		return getSQLXML(findColumn(columnLabel));
+	}
+
+	public synchronized boolean isClosed() throws SQLException {
+		return this.isClosed();
+	}
+
+	public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
+		updateAsciiStream(findColumn(columnLabel), x);
+		
+	}
+
+	public void updateAsciiStream(int columnIndex, InputStream x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateAsciiStream(String columnLabel, InputStream x, long length) throws
SQLException {
+		updateAsciiStream(findColumn(columnLabel), x, length);
+	}
+
+	public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
+		updateBinaryStream(findColumn(columnLabel), x);
+	}
+
+	public void updateBinaryStream(int columnIndex, InputStream x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateBinaryStream(String columnLabel, InputStream x, long length) throws
SQLException {
+		updateBinaryStream(findColumn(columnLabel), x, length);
+	}
+
+	public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
+		throw new NotUpdatable();
+	}
+
+	public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException
{
+		updateBlob(findColumn(columnLabel), inputStream);
+	}
+
+	public void updateBlob(int columnIndex, InputStream inputStream, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateBlob(String columnLabel, InputStream inputStream, long length) throws
SQLException {
+		updateBlob(findColumn(columnLabel), inputStream, length);
+	}
+
+	public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException
{
+		updateCharacterStream(findColumn(columnLabel), reader);
+	}
+
+	public void updateCharacterStream(int columnIndex, Reader x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateCharacterStream(String columnLabel, Reader reader, long length) throws
SQLException {
+		updateCharacterStream(findColumn(columnLabel), reader, length);
+	}
+
+	public void updateClob(int columnIndex, Reader reader) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateClob(String columnLabel, Reader reader) throws SQLException {
+		updateClob(findColumn(columnLabel), reader);
+	}
+
+	public void updateClob(int columnIndex, Reader reader, long length) throws SQLException
{
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateClob(String columnLabel, Reader reader, long length) throws
SQLException {
+		updateClob(findColumn(columnLabel), reader, length);
+	}
+
+	public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNCharacterStream(String columnLabel, Reader reader) throws
SQLException {
+		updateNCharacterStream(findColumn(columnLabel), reader);
+		
+	}
+
+	public void updateNCharacterStream(int columnIndex, Reader x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNCharacterStream(String columnLabel, Reader reader, long length)
throws SQLException {
+		updateNCharacterStream(findColumn(columnLabel), reader, length);
+	}
+
+	public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNClob(int columnIndex, Reader reader) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNClob(String columnLabel, Reader reader) throws SQLException {
+		updateNClob(findColumn(columnLabel), reader);
+		
+	}
+
+	public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException
{
+		throw new NotUpdatable();
+	}
+
+	public void updateNClob(String columnLabel, Reader reader, long length) throws
SQLException {
+		updateNClob(findColumn(columnLabel), reader, length);
+	}
+
+	public void updateNString(int columnIndex, String nString) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNString(String columnLabel, String nString) throws SQLException {
+		updateNString(findColumn(columnLabel), nString);
+	}
+
+	public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
+		updateSQLXML(findColumn(columnLabel), xmlObject);
+		
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/ResultSetMetaData.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -27,6 +27,8 @@
 import java.sql.SQLException;
 import java.sql.Types;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
+
 /**
  * A ResultSetMetaData object can be used to find out about the types and
  * properties of the columns in a ResultSet
@@ -803,4 +805,12 @@
 			return "java.lang.Object"; //$NON-NLS-1$
 		}
 	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/SQLError.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/SQLError.java	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/SQLError.java	2006-09-19 01:47:23 UTC (rev 5749)
@@ -39,13 +39,15 @@
 import com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException;
 import com.mysql.jdbc.exceptions.MySQLSyntaxErrorException;
 import com.mysql.jdbc.exceptions.MySQLTransactionRollbackException;
+import com.mysql.jdbc.exceptions.MySQLTransientConnectionException;
 
 /**
  * SQLError is a utility class that maps MySQL error codes to X/Open error codes
  * as is required by the JDBC spec.
  * 
  * @author Mark Matthews <mmatthew_at_worldserver.com>
- * @version $Id$
+ * @version $Id: SQLError.java 5122 2006-04-03 15:37:11 +0000 (Mon, 03 Apr 2006)
+ *          mmatthews $
  */
 public class SQLError {
 	static final int ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196;
@@ -127,12 +129,21 @@
 	public static final String SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE = "08001";
//$NON-NLS-1$
 
 	public static final String SQL_STATE_WRONG_NO_OF_PARAMETERS = "07001"; //$NON-NLS-1$
-	
-	public static final String SQL_STATE_INVALID_TRANSACTION_TERMINATION = "2D000";
//$NON_NLS-1$
 
+	public static final String SQL_STATE_INVALID_TRANSACTION_TERMINATION = "2D000"; //
$NON_NLS-1$
+
+	private static boolean isJdbc4;
+
 	private static Map sqlStateMessages;
 
 	static {
+		try {
+			Class.forName("java.sql.NClob");
+			isJdbc4 = true;
+		} catch (Throwable t) {
+			isJdbc4 = false;
+		}
+
 		sqlStateMessages = new HashMap();
 		sqlStateMessages.put(SQL_STATE_DISCONNECT_ERROR, Messages
 				.getString("SQLError.35")); //$NON-NLS-1$
@@ -883,31 +894,7 @@
 
 	public static SQLException createSQLException(String message,
 			String sqlState) {
-		if (sqlState != null) {
-			if (sqlState.startsWith("08")) {
-				return new MySQLNonTransientConnectionException(message,
-						sqlState);
-			}
-
-			if (sqlState.startsWith("22")) {
-				return new MySQLDataException(message, sqlState);
-			}
-
-			if (sqlState.startsWith("23")) {
-				return new MySQLIntegrityConstraintViolationException(message,
-						sqlState);
-			}
-
-			if (sqlState.startsWith("42")) {
-				return new MySQLSyntaxErrorException(message, sqlState);
-			}
-
-			if (sqlState.startsWith("40")) {
-				return new MySQLTransactionRollbackException(message, sqlState);
-			}
-		}
-
-		return new SQLException(message, sqlState);
+		return createSQLException(message, sqlState, 0);
 	}
 
 	public static SQLException createSQLException(String message) {
@@ -916,33 +903,75 @@
 
 	public static SQLException createSQLException(String message,
 			String sqlState, int vendorErrorCode) {
+		return createSQLException(message, sqlState, vendorErrorCode, false);
+	}
+	
+	public static SQLException createSQLException(String message,
+			String sqlState, int vendorErrorCode,
+			boolean isTransient) {
 		if (sqlState != null) {
 			if (sqlState.startsWith("08")) {
-				return new MySQLNonTransientConnectionException(message,
-						sqlState, vendorErrorCode);
+				if (isTransient) {
+					if (!isJdbc4) {
+						return new MySQLTransientConnectionException(message,
+								sqlState, vendorErrorCode);
+					}
+					
+					return new com.mysql.jdbc.exceptions.jdbc4.MySQLTransientConnectionException(
+							message, sqlState, vendorErrorCode);
+				}
+				
+				if (!isJdbc4) {
+					return new MySQLNonTransientConnectionException(message,
+							sqlState, vendorErrorCode);
+				}
+				
+				return new com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException(
+						message, sqlState, vendorErrorCode);
 			}
 
 			if (sqlState.startsWith("22")) {
-				return new MySQLDataException(message, sqlState,
-						vendorErrorCode);
+				if (!isJdbc4) {
+					return new MySQLDataException(message, sqlState,
+							vendorErrorCode);
+				}
+				
+				return new com.mysql.jdbc.exceptions.jdbc4.MySQLDataException(
+						message, sqlState, vendorErrorCode);
 			}
 
 			if (sqlState.startsWith("23")) {
-				return new MySQLIntegrityConstraintViolationException(message,
-						sqlState, vendorErrorCode);
+
+				if (!isJdbc4) {
+					return new MySQLIntegrityConstraintViolationException(
+							message, sqlState, vendorErrorCode);
+				}
+				
+				return new
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException(
+						message, sqlState, vendorErrorCode);
 			}
 
 			if (sqlState.startsWith("42")) {
-				return new MySQLSyntaxErrorException(message, sqlState,
-						vendorErrorCode);
+				if (!isJdbc4) {
+					return new MySQLSyntaxErrorException(message, sqlState,
+							vendorErrorCode);
+				}
+				
+				return new com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException(
+						message, sqlState, vendorErrorCode);
 			}
 
 			if (sqlState.startsWith("40")) {
-				return new MySQLTransactionRollbackException(message, sqlState,
-						vendorErrorCode);
+				if (!isJdbc4) {
+					return new MySQLTransactionRollbackException(message,
+							sqlState, vendorErrorCode);
+				}
+				
+				return new com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException(
+						message, sqlState, vendorErrorCode);
 			}
 		}
-
+		
 		return new SQLException(message, sqlState, vendorErrorCode);
 	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2006-09-19 01:45:03
UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2006-09-19 01:47:23
UTC (rev 5749)
@@ -41,6 +41,7 @@
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.Date;
+import java.sql.NClob;
 import java.sql.ParameterMetaData;
 import java.sql.Ref;
 import java.sql.SQLException;
@@ -280,7 +281,8 @@
 	 * @throws SQLException
 	 *             If an error occurs
 	 */
-	public ServerPreparedStatement(Connection conn, String sql, String catalog)
+	public ServerPreparedStatement(Connection conn, String sql, String catalog,
+			int resultSetType, int resultSetConcurrency)
 			throws SQLException {
 		super(conn, catalog);
 
@@ -320,6 +322,9 @@
 			throw SQLError.createSQLException(ex.toString(),
 					SQLError.SQL_STATE_GENERAL_ERROR);
 		}
+		
+		setResultSetType(resultSetType);
+		setResultSetConcurrency(resultSetConcurrency);
 	}
 
 	/**
@@ -1151,11 +1156,11 @@
 			CancelTask timeoutTask = null;
 
 			try {
-				if (this.timeout != 0
+				if (this.timeoutInMillis != 0
 						&& this.connection.versionMeetsMinimum(5, 0, 0)) {
 					timeoutTask = new CancelTask();
 					this.connection.getCancelTimer().schedule(timeoutTask, 
-							this.timeout);
+							this.timeoutInMillis);
 				}
 				
 				Buffer resultPacket = mysql.sendCommand(MysqlDefs.COM_EXECUTE,
@@ -2422,4 +2427,101 @@
 	protected long getServerStatementId() {
 		return serverStatementId;
 	}
+
+	   /**
+     * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader,
+     *      long)
+     */
+    public void setNCharacterStream(int parameterIndex, Reader reader, long length)
+            throws SQLException {
+        // can't take if characterEncoding isn't utf8
+        if (!this.charEncoding.equalsIgnoreCase("UTF-8")
+                && !this.charEncoding.equalsIgnoreCase("utf8")) {
+            throw SQLError.createSQLException(
+                "Can not call setNCharacterStream() when connection character set isn't
UTF-8");
+        }
+        
+        checkClosed();
+        
+        if (reader == null) {
+            setNull(parameterIndex, java.sql.Types.BINARY);
+        } else {
+            BindValue binding = getBinding(parameterIndex, true);
+            setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
+
+            binding.value = reader;
+            binding.isNull = false;
+            binding.isLongData = true;
+
+            if (this.connection.getUseStreamLengthsInPrepStmts()) {
+                binding.bindLength = length;
+            } else {
+                binding.bindLength = -1;
+            }
+        }
+    }
+
+    /**
+     * @see java.sql.PreparedStatement#setNClob(int, java.sql.NClob)
+     */
+    public void setNClob(int parameterIndex, NClob x) throws SQLException {
+        setNClob(parameterIndex, x.getCharacterStream(), 
+        		this.connection.getUseStreamLengthsInPrepStmts()
+                ? x.length() : -1);
+    }
+
+	/**
+	 * JDBC 4.0 Set a NCLOB parameter.
+	 * 
+	 * @param parameterIndex
+	 *            the first parameter is 1, the second is 2, ...
+	 * @param reader
+	 *            the java reader which contains the UNICODE data
+	 * @param length
+	 *            the number of characters in the stream
+	 * 
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void setNClob(int parameterIndex, Reader reader, long length)
+			throws SQLException {
+		// can't take if characterEncoding isn't utf8
+        if (!this.charEncoding.equalsIgnoreCase("UTF-8")
+                && !this.charEncoding.equalsIgnoreCase("utf8")) {
+            throw SQLError.createSQLException(
+                "Can not call setNClob() when connection character set isn't UTF-8");
+        }
+        
+        checkClosed();
+        
+        if (reader == null) {
+            setNull(parameterIndex, java.sql.Types.NCLOB);
+        } else {
+            BindValue binding = getBinding(parameterIndex, true);
+            setType(binding, MysqlDefs.FIELD_TYPE_BLOB);
+
+            binding.value = reader;
+            binding.isNull = false;
+            binding.isLongData = true;
+
+            if (this.connection.getUseStreamLengthsInPrepStmts()) {
+                binding.bindLength = length;
+            } else {
+                binding.bindLength = -1;
+            }
+        }
+	}
+
+	/**
+	 * @see java.sql.PreparedStatement#setNString(int, java.lang.String)
+	 */
+	public void setNString(int parameterIndex, String x) throws SQLException {
+	    if (this.charEncoding.equalsIgnoreCase("UTF-8")
+	            || this.charEncoding.equalsIgnoreCase("utf8")) {
+	        setString(parameterIndex, x);
+	    } else {
+	        throw SQLError.createSQLException(
+	            "Can not call setNString() when connection character set isn't UTF-8");
+	    }
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/Statement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Statement.java	2006-09-19 01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/Statement.java	2006-09-19 01:47:23 UTC (rev 5749)
@@ -24,6 +24,7 @@
  */
 package com.mysql.jdbc;
 
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 import com.mysql.jdbc.exceptions.MySQLTimeoutException;
 import com.mysql.jdbc.profiler.ProfileEventSink;
 import com.mysql.jdbc.profiler.ProfilerEvent;
@@ -213,7 +214,7 @@
 	protected int statementId;
 
 	/** The timeout for a query */
-	protected int timeout = 0;
+	protected int timeoutInMillis = 0;
 
 	/** The update count for this statement */
 	protected long updateCount = -1;
@@ -615,11 +616,11 @@
 				CancelTask timeoutTask = null;
 
 				try {
-					if (this.timeout != 0
+					if (this.timeoutInMillis != 0
 							&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
 						timeoutTask = new CancelTask();
 						Connection.getCancelTimer().schedule(timeoutTask, 
-								this.timeout);
+								this.timeoutInMillis);
 					}
 
 					String oldCatalog = null;
@@ -1096,11 +1097,11 @@
 			CancelTask timeoutTask = null;
 
 			try {
-				if (this.timeout != 0
+				if (this.timeoutInMillis != 0
 						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
 					timeoutTask = new CancelTask();
 					Connection.getCancelTimer().schedule(timeoutTask, 
-							this.timeout);
+							this.timeoutInMillis);
 				}
 
 				String oldCatalog = null;
@@ -1282,11 +1283,11 @@
 			CancelTask timeoutTask = null;
 
 			try {
-				if (this.timeout != 0
+				if (this.timeoutInMillis != 0
 						&& locallyScopedConn.versionMeetsMinimum(5, 0, 0)) {
 					timeoutTask = new CancelTask();
 					Connection.getCancelTimer().schedule(timeoutTask, 
-							this.timeout);
+							this.timeoutInMillis);
 				}
 
 				String oldCatalog = null;
@@ -1745,7 +1746,7 @@
 	 *                if a database access error occurs
 	 */
 	public int getQueryTimeout() throws SQLException {
-		return this.timeout;
+		return this.timeoutInMillis / 1000;
 	}
 
 	/**
@@ -2229,7 +2230,7 @@
 					SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
 		}
 
-		this.timeout = seconds;
+		this.timeoutInMillis = seconds * 1000;
 	}
 
 	/**
@@ -2299,4 +2300,26 @@
 				&& this.resultSetConcurrency == ResultSet.CONCUR_READ_ONLY
 				&& this.resultSetType == ResultSet.TYPE_FORWARD_ONLY;
 	}
+
+	public synchronized boolean isClosed() throws SQLException {
+		return this.isClosed;
+	}
+
+	private boolean isPoolable = true;
+	
+	public boolean isPoolable() throws SQLException {
+		return this.isPoolable;
+	}
+
+	public void setPoolable(boolean poolable) throws SQLException {
+		this.isPoolable = poolable;
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/StringUtils.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/StringUtils.java	2006-09-19 01:45:03 UTC (rev
5748)
+++ trunk/connector-j/src/com/mysql/jdbc/StringUtils.java	2006-09-19 01:47:23 UTC (rev
5749)
@@ -1445,4 +1445,8 @@
 
 		return s.getBytes();
 	}
+	
+	public static boolean isNullOrEmpty(String toTest) {
+		return (toTest == null || toTest.length() == 0);
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -27,9 +27,14 @@
 import com.mysql.jdbc.profiler.ProfileEventSink;
 import com.mysql.jdbc.profiler.ProfilerEvent;
 
+import java.io.InputStream;
+import java.io.Reader;
 import java.math.BigDecimal;
 
+import java.sql.NClob;
+import java.sql.RowId;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -2438,4 +2443,237 @@
 			java.sql.Timestamp x) throws SQLException {
 		updateTimestamp(findColumn(columnName), x);
 	}
+	
+	public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateAsciiStream(int columnIndex, InputStream x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+	
+	public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateBinaryStream(int columnIndex, InputStream x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
+		throw new NotUpdatable();
+	}
+
+	public void updateBlob(int columnIndex, InputStream inputStream, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+
+	public void updateCharacterStream(int columnIndex, Reader x, long length) throws
SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateClob(int columnIndex, Reader reader) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateClob(int columnIndex, Reader reader, long length) throws SQLException
{
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNCharacterStream(int columnIndex, Reader x, long length) throws
SQLException {
+		updateNCharacterStream(columnIndex, x, (int) length);
+		
+	}
+	
+
+	public void updateNClob(int columnIndex, Reader reader) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+
+	public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException
{
+		throw new NotUpdatable();
+	}
+
+	public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
+		throw new NotUpdatable();
+		
+	}
+	
+	
+	
+	public void updateRowId(int columnIndex, RowId x) throws SQLException {
+		throw new NotUpdatable();
+	}
+
+	/**
+	 * JDBC 4.0 Update a column with a character stream value. The updateXXX()
+	 * methods are used to update column values in the current row, or the
+	 * insert row. The updateXXX() methods do not update the underlying
+	 * database, instead the updateRow() or insertRow() methods are called to
+	 * update the database.
+	 * 
+	 * @param columnIndex
+	 *            the first column is 1, the second is 2, ...
+	 * @param x
+	 *            the new column value
+	 * @param length
+	 *            the length of the stream
+	 * 
+	 * @exception SQLException
+	 *                if a database-access error occurs
+	 */
+	public synchronized void updateNCharacterStream(int columnIndex,
+	        java.io.Reader x, int length) throws SQLException {
+	    String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet();
+	    if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
+	        throw new SQLException(
+	                "Can not call updateNCharacterStream() when field's character set isn't
UTF-8");
+	    }
+	    
+	    if (!this.onInsertRow) {
+	        if (!this.doingUpdates) {
+	            this.doingUpdates = true;
+	            syncUpdate();
+	        }
+	
+	        this.updater.setNCharacterStream(columnIndex, x, length);
+	    } else {
+	        this.inserter.setNCharacterStream(columnIndex, x, length);
+	
+	        if (x == null) {
+	            this.thisRow[columnIndex - 1] = null;
+	        } else {
+	            this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
+	        }
+	    }
+	}
+
+	/**
+	 * JDBC 4.0 Update a column with a character stream value. The updateXXX()
+	 * methods are used to update column values in the current row, or the
+	 * insert row. The updateXXX() methods do not update the underlying
+	 * database, instead the updateRow() or insertRow() methods are called to
+	 * update the database.
+	 * 
+	 * @param columnName
+	 *            the name of the column
+	 * @param reader
+	 *            the new column value
+	 * @param length
+	 *            of the stream
+	 * 
+	 * @exception SQLException
+	 *                if a database-access error occurs
+	 */
+	public synchronized void updateNCharacterStream(String columnName,
+	        java.io.Reader reader, int length) throws SQLException {
+	    updateNCharacterStream(findColumn(columnName), reader, length);
+	}
+
+	/**
+	 * @see ResultSet#updateNClob(int, NClob)
+	 */
+	public void updateNClob(int columnIndex, java.sql.NClob nClob)
+	        throws SQLException {
+	    String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet();
+	    if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
+	        throw new SQLException("Can not call updateNClob() when field's character set
isn't UTF-8");
+	    }
+	    
+	    if (nClob == null) {
+	        updateNull(columnIndex);
+	    } else {
+	        updateNCharacterStream(columnIndex, nClob.getCharacterStream(),
+	                (int) nClob.length());
+	    }
+	}
+
+	/**
+	 * @see ResultSet#updateClob(int, Clob)
+	 */
+	public void updateNClob(String columnName, java.sql.NClob nClob)
+	        throws SQLException {
+	    updateNClob(findColumn(columnName), nClob);
+	}
+
+	/**
+	 * JDBC 4.0 Update a column with NATIONAL CHARACTER. The updateXXX() methods are
+	 * used to update column values in the current row, or the insert row. The
+	 * updateXXX() methods do not update the underlying database, instead the
+	 * updateRow() or insertRow() methods are called to update the database.
+	 * 
+	 * @param columnIndex
+	 *            the first column is 1, the second is 2, ...
+	 * @param x
+	 *            the new column value
+	 * 
+	 * @exception SQLException
+	 *                if a database-access error occurs
+	 */
+	public synchronized void updateNString(int columnIndex, String x)
+	        throws SQLException {
+	    String fieldEncoding = this.fields[columnIndex - 1].getCharacterSet();
+	    if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
+	        throw new SQLException("Can not call updateNString() when field's character set
isn't UTF-8");
+	    }
+	    
+	    if (!this.onInsertRow) {
+	        if (!this.doingUpdates) {
+	            this.doingUpdates = true;
+	            syncUpdate();
+	        }
+	
+	        this.updater.setNString(columnIndex, x);
+	    } else {
+	        this.inserter.setNString(columnIndex, x);
+	
+	        if (x == null) {
+	            this.thisRow[columnIndex - 1] = null;
+	        } else {
+	            this.thisRow[columnIndex - 1] = StringUtils.getBytes(x,
+	                        this.charConverter, fieldEncoding,
+	                        this.connection.getServerCharacterEncoding(),
+	                        this.connection.parserKnowsUnicode());
+	        }
+	    }
+	}
+
+	/**
+	 * JDBC 4.0 Update a column with NATIONAL CHARACTER. The updateXXX() methods are
+	 * used to update column values in the current row, or the insert row. The
+	 * updateXXX() methods do not update the underlying database, instead the
+	 * updateRow() or insertRow() methods are called to update the database.
+	 * 
+	 * @param columnName
+	 *            the name of the column
+	 * @param x
+	 *            the new column value
+	 * 
+	 * @exception SQLException
+	 *                if a database-access error occurs
+	 */
+	public synchronized void updateNString(String columnName, String x)
+	        throws SQLException {
+	    updateNString(findColumn(columnName), x);
+	}
 }

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/JDBC40NotYetImplementedException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/JDBC40NotYetImplementedException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/JDBC40NotYetImplementedException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,18 @@
+package com.mysql.jdbc.exceptions;
+
+public class JDBC40NotYetImplementedException extends RuntimeException {
+
+	public JDBC40NotYetImplementedException() {
+		// TODO Auto-generated constructor stub
+	}
+
+	public JDBC40NotYetImplementedException(String reason) {
+		super(reason);
+		// TODO Auto-generated constructor stub
+	}
+
+	public JDBC40NotYetImplementedException(Throwable cause) {
+		super(cause);
+		// TODO Auto-generated constructor stub
+	}
+}

Added: trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLDataException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLDataException;
+
+public class MySQLDataException extends SQLDataException {
+
+	public MySQLDataException() {
+		super();
+	}
+
+	public MySQLDataException(String reason, String SQLState, int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLDataException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLDataException(String reason) {
+		super(reason);
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLIntegrityConstraintViolationException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLIntegrityConstraintViolationException;
+
+public class MySQLIntegrityConstraintViolationException extends
+		SQLIntegrityConstraintViolationException {
+
+	public MySQLIntegrityConstraintViolationException() {
+		super();
+	}
+
+	public MySQLIntegrityConstraintViolationException(String reason, String SQLState, int
vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLIntegrityConstraintViolationException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLIntegrityConstraintViolationException(String reason) {
+		super(reason);
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLInvalidAuthorizationSpecException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLInvalidAuthorizationSpecException;
+
+public class MySQLInvalidAuthorizationSpecException extends
+		SQLInvalidAuthorizationSpecException {
+
+	public MySQLInvalidAuthorizationSpecException() {
+		super();
+	}
+
+	public MySQLInvalidAuthorizationSpecException(String reason, String SQLState, int
vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLInvalidAuthorizationSpecException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLInvalidAuthorizationSpecException(String reason) {
+		super(reason);
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientConnectionException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLNonTransientConnectionException;
+
+public class MySQLNonTransientConnectionException extends
+		SQLNonTransientConnectionException {
+
+	public MySQLNonTransientConnectionException() {
+		super();
+	}
+
+	public MySQLNonTransientConnectionException(String reason, String SQLState, int
vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLNonTransientConnectionException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLNonTransientConnectionException(String reason) {
+		super(reason);
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLNonTransientException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLException;
+import java.sql.SQLNonTransientException;
+
+public class MySQLNonTransientException extends SQLNonTransientException {
+
+	public MySQLNonTransientException() {
+		super();
+	}
+
+	public MySQLNonTransientException(String reason, String SQLState, int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLNonTransientException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLNonTransientException(String reason) {
+		super(reason);
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLSyntaxErrorException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLSyntaxErrorException;
+
+public class MySQLSyntaxErrorException extends SQLSyntaxErrorException {
+
+	public MySQLSyntaxErrorException() {
+		super();
+	}
+
+	public MySQLSyntaxErrorException(String reason, String SQLState, int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLSyntaxErrorException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLSyntaxErrorException(String reason) {
+		super(reason);
+	}
+}

Added: trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTimeoutException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLTimeoutException;
+
+public class MySQLTimeoutException extends SQLTimeoutException {
+
+	public MySQLTimeoutException(String reason, String SQLState, int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLTimeoutException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLTimeoutException(String reason) {
+		super(reason);
+	}
+
+	public MySQLTimeoutException() {
+		super("Statement cancelled due to timeout or client request");
+	}
+
+	public int getErrorCode() {
+		// TODO Auto-generated method stub
+		return super.getErrorCode();
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransactionRollbackException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLTransactionRollbackException;
+
+public class MySQLTransactionRollbackException extends SQLTransactionRollbackException {
+
+	public MySQLTransactionRollbackException(String reason, String SQLState,
+			int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLTransactionRollbackException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLTransactionRollbackException(String reason) {
+		super(reason);
+	}
+
+	public MySQLTransactionRollbackException() {
+		super();
+	}
+}

Added:
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientConnectionException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLTransientConnectionException;
+
+public class MySQLTransientConnectionException extends SQLTransientConnectionException {
+
+	public MySQLTransientConnectionException(String reason, String SQLState,
+			int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLTransientConnectionException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLTransientConnectionException(String reason) {
+		super(reason);
+	}
+
+	public MySQLTransientConnectionException() {
+		super();
+	}
+}

Added: trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/exceptions/jdbc4/MySQLTransientException.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2005 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.exceptions.jdbc4;
+
+import java.sql.SQLException;
+import java.sql.SQLTransientException;
+
+public class MySQLTransientException extends SQLTransientException {
+
+	public MySQLTransientException(String reason, String SQLState, int vendorCode) {
+		super(reason, SQLState, vendorCode);
+	}
+
+	public MySQLTransientException(String reason, String SQLState) {
+		super(reason, SQLState);
+	}
+
+	public MySQLTransientException(String reason) {
+		super(reason);
+	}
+
+	public MySQLTransientException() {
+		super();
+	}
+}

Modified:
trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/CallableStatementWrapper.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -33,14 +33,18 @@
 import java.sql.CallableStatement;
 import java.sql.Clob;
 import java.sql.Date;
+import java.sql.NClob;
 import java.sql.Ref;
+import java.sql.RowId;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.Calendar;
 import java.util.Map;
 
 import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 
 /**
  * Wraps callable statements created by pooled connections.
@@ -1761,4 +1765,838 @@
 		return null;
 	}
 
+	public Reader getCharacterStream(int parameterIndex) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getCharacterStream(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public Reader getCharacterStream(String parameterName) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getCharacterStream(parameterName);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public Reader getNCharacterStream(int parameterIndex) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getCharacterStream(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public Reader getNCharacterStream(String parameterName) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getNCharacterStream(parameterName);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public NClob getNClob(int parameterIndex) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getNClob(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public NClob getNClob(String parameterName) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getNClob(parameterName);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public String getNString(int parameterIndex) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getNString(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public String getNString(String parameterName) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getNString(parameterName);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public RowId getRowId(int parameterIndex) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getRowId(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public RowId getRowId(String parameterName) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getRowId(parameterName);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public SQLXML getSQLXML(int parameterIndex) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getSQLXML(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public SQLXML getSQLXML(String parameterName) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.getSQLXML(parameterName);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return null;
+	}
+
+	public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setAsciiStream(parameterName, x) ;
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setAsciiStream(String parameterName, InputStream x, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setAsciiStream(parameterName, x, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBinaryStream(parameterName, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBinaryStream(String parameterName, InputStream x, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBinaryStream(parameterName, x, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(String parameterName, Blob x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBlob(parameterName, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBlob(parameterName, inputStream);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(String parameterName, InputStream inputStream, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBlob(parameterName, inputStream, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setCharacterStream(String parameterName, Reader reader) throws SQLException
{
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setCharacterStream(parameterName, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setCharacterStream(String parameterName, Reader reader, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setCharacterStream(parameterName, reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(String parameterName, Clob x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setClob(parameterName, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(String parameterName, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setClob(parameterName, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(String parameterName, Reader reader, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setClob(parameterName, reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNCharacterStream(String parameterName, Reader value) throws SQLException
{
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNCharacterStream(parameterName, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNCharacterStream(String parameterName, Reader value, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNCharacterStream(parameterName, value, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(String parameterName, NClob value) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNClob(parameterName, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(String parameterName, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNClob(parameterName, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(String parameterName, Reader reader, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNClob(parameterName, reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNString(String parameterName, String value) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNString(parameterName, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setRowId(String parameterName, RowId x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setRowId(parameterName, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setSQLXML(parameterName, xmlObject);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setAsciiStream(parameterIndex, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setAsciiStream(int parameterIndex, InputStream x, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setAsciiStream(parameterIndex, x, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBinaryStream(parameterIndex, x) ;
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBinaryStream(int parameterIndex, InputStream x, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBinaryStream(parameterIndex, x, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBlob(parameterIndex, inputStream);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(int parameterIndex, InputStream inputStream, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setBlob(parameterIndex, inputStream, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setCharacterStream(parameterIndex, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setCharacterStream(int parameterIndex, Reader reader, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.getCharacterStream(parameterIndex);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(int parameterIndex, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setClob(parameterIndex, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
{
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setClob(parameterIndex, reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNCharacterStream(parameterIndex, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	
+	}
+
+	public void setNCharacterStream(int parameterIndex, Reader value, long length) throws
SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNCharacterStream(parameterIndex, value, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(int parameterIndex, NClob value) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNClob(parameterIndex, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNClob(parameterIndex, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
{
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNClob(parameterIndex, reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNString(int parameterIndex, String value) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setNString(parameterIndex, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setRowId(int parameterIndex, RowId x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setRowId(parameterIndex, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setSQLXML(parameterIndex, xmlObject);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+	}
+
+	public boolean isClosed() throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						.isClosed();
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return true;
+	}
+
+	public boolean isPoolable() throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((CallableStatement) this.wrappedStmt)
+						. isPoolable();
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return false;
+	}
+
+	public void setPoolable(boolean poolable) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((CallableStatement) this.wrappedStmt)
+						.setPoolable(poolable);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-09-19
01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/ConnectionWrapper.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -24,13 +24,23 @@
  */
 package com.mysql.jdbc.jdbc2.optional;
 
+import java.sql.Array;
+import java.sql.BaseQuery;
+import java.sql.Blob;
+import java.sql.Clob;
 import java.sql.Connection;
+import java.sql.NClob;
+import java.sql.SQLClientInfoException;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 import java.sql.Savepoint;
 import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Properties;
 
 import com.mysql.jdbc.MysqlErrorNumbers;
 import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 
 /**
  * This class serves as a wrapper for the org.gjt.mm.mysql.jdbc2.Connection
@@ -837,4 +847,142 @@
 			this.mc.ping();
 		}
 	}
+
+	public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.createArrayOf(typeName, elements);
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public Blob createBlob() throws SQLException {
+		checkClosed();
+		
+		return this.mc.createBlob();
+	}
+
+	public Clob createClob() throws SQLException {
+		return this.mc.createClob();
+	}
+
+	public NClob createNClob() throws SQLException {
+		return this.mc.createNClob();
+	}
+
+	public BaseQuery createQueryObject(Class arg0) throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.createQueryObject(arg0);
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public BaseQuery createQueryObject(Class arg0, Connection arg1) throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.createQueryObject(arg0, arg1);
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public SQLXML createSQLXML() throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.createSQLXML();
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.createStruct(typeName, attributes);
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public Properties getClientInfo() throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.getClientInfo();
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public String getClientInfo(String name) throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.getClientInfo(name);
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return null; // we don't reach this code, compiler can't tell
+	}
+
+	public boolean isValid(int timeout) throws SQLException {
+		checkClosed();
+
+		try {
+			return this.mc.isValid(timeout);
+		} catch (SQLException sqlException) {
+			checkAndFireConnectionError(sqlException);
+		}
+
+		return false; // we don't reach this code, compiler can't tell
+	}
+
+	public void setClientInfo(Properties properties) throws SQLClientInfoException {
+		//checkClosed();
+
+		try {
+			this.mc.setClientInfo(properties);
+		} catch (SQLException sqlException) {
+			//checkAndFireConnectionError(sqlException);
+		}	
+	}
+
+	public void setClientInfo(String name, String value) throws SQLClientInfoException {
+		//checkClosed();
+
+		try {
+			this.mc.setClientInfo(name, value);
+		} catch (SQLException sqlException) {
+			//checkAndFireConnectionError(sqlException);
+		}
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified:
trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java
===================================================================
---
trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/PreparedStatementWrapper.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -25,6 +25,7 @@
 package com.mysql.jdbc.jdbc2.optional;
 
 import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 
 import java.io.InputStream;
 import java.io.Reader;
@@ -37,12 +38,15 @@
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.Date;
+import java.sql.NClob;
 import java.sql.ParameterMetaData;
 import java.sql.PreparedStatement;
 import java.sql.Ref;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
+import java.sql.RowId;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 import java.sql.Time;
 import java.sql.Timestamp;
 
@@ -795,7 +799,7 @@
 		}
 
 		return false; // we actually never get here, but the compiler can't
-						// figure
+		// figure
 
 		// that out
 	}
@@ -824,7 +828,7 @@
 		}
 
 		return null; // we actually never get here, but the compiler can't
-						// figure
+		// figure
 
 		// that out
 	}
@@ -851,4 +855,342 @@
 
 		// that out
 	}
+
+	public void setAsciiStream(int parameterIndex, InputStream x)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setAsciiStream(
+						parameterIndex, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setAsciiStream(int parameterIndex, InputStream x, long length)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setAsciiStream(
+						parameterIndex, x, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBinaryStream(int parameterIndex, InputStream x)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setBinaryStream(
+						parameterIndex, x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBinaryStream(int parameterIndex, InputStream x, long length)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setBinaryStream(
+						parameterIndex, x, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(int parameterIndex, InputStream inputStream)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex,
+						inputStream);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setBlob(int parameterIndex, InputStream inputStream, long length)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setBlob(parameterIndex,
+						inputStream, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setCharacterStream(int parameterIndex, Reader reader)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setCharacterStream(
+						parameterIndex, reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setCharacterStream(int parameterIndex, Reader reader,
+			long length) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setCharacterStream(
+						parameterIndex, reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(int parameterIndex, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setClob(parameterIndex,
+						reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setClob(int parameterIndex, Reader reader, long length)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setClob(parameterIndex,
+						reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNCharacterStream(int parameterIndex, Reader value)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setNCharacterStream(
+						parameterIndex, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNCharacterStream(int parameterIndex, Reader value,
+			long length) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setNCharacterStream(
+						parameterIndex, value, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(int parameterIndex, NClob value) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex,
+						value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex,
+						reader);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNClob(int parameterIndex, Reader reader, long length)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setNClob(parameterIndex,
+						reader, length);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setNString(int parameterIndex, String value)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setNString(
+						parameterIndex, value);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setRowId(int parameterIndex, RowId x) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setRowId(parameterIndex,
+						x);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public void setSQLXML(int parameterIndex, SQLXML xmlObject)
+			throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setSQLXML(
+						parameterIndex, xmlObject);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public boolean isClosed() throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((PreparedStatement) this.wrappedStmt).isClosed();
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+
+		return true;
+	}
+
+	public boolean isPoolable() throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return ((PreparedStatement) this.wrappedStmt).isPoolable();
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+
+		return false;
+	}
+
+	public void setPoolable(boolean poolable) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				((PreparedStatement) this.wrappedStmt).setPoolable(poolable);
+			} else {
+				throw SQLError.createSQLException(
+						"No operations allowed after statement closed",
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java	2006-09-19
01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/com/mysql/jdbc/jdbc2/optional/StatementWrapper.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -25,6 +25,7 @@
 package com.mysql.jdbc.jdbc2.optional;
 
 import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.exceptions.JDBC40NotYetImplementedException;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -826,4 +827,55 @@
 			checkAndFireConnectionError(sqlEx);
 		}
 	}
+
+	public boolean isClosed() throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return this.wrappedStmt.isClosed();
+			} else {
+				throw SQLError.createSQLException("Statement already closed",
+						SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return true;
+	}
+
+	public boolean isPoolable() throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				return this.wrappedStmt.isPoolable();
+			} else {
+				throw SQLError.createSQLException("Statement already closed",
+						SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+		
+		return true;
+	}
+
+	public void setPoolable(boolean poolable) throws SQLException {
+		try {
+			if (this.wrappedStmt != null) {
+				this.wrappedStmt.setPoolable(poolable);
+			} else {
+				throw SQLError.createSQLException("Statement already closed",
+						SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+			}
+		} catch (SQLException sqlEx) {
+			checkAndFireConnectionError(sqlEx);
+		}
+	}
+
+	public boolean isWrapperFor(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
+
+	public Object unwrap(Class arg0) throws SQLException {
+		throw new JDBC40NotYetImplementedException();
+	}
 }

Modified: trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
---
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-09-19
01:45:03 UTC (rev 5748)
+++
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -787,4 +787,73 @@
 			}
 		}
 	}
+
+	/**
+	 * Tests workaround for server crash when calling stored procedures
+	 * via a server-side prepared statement (driver now detects 
+	 * prepare(stored procedure) and substitutes client-side prepared statement).
+	 * 
+	 * @throws Exception if the test fails
+	 */
+	public void testBug22297() throws Exception {
+		if (versionMeetsMinimum(5, 0)) {
+			this.stmt.executeUpdate("DROP PROCEDURE IF EXISTS testBug22297");
+			
+			createTable("tblTestBug2297_1", "("
+					+ "id varchar(20) NOT NULL default '',"
+					+ "Income double(19,2) default NULL)");	
+			
+			createTable("tblTestBug2297_2", "("
+					+ "id varchar(20) NOT NULL default ''," 
+					+ "CreatedOn datetime default NULL)");
+			
+			this.stmt.executeUpdate("CREATE PROCEDURE testBug22297(pcaseid INT)"
+					+ "BEGIN"
+					+ "\nSET @sql = \"DROP TEMPORARY TABLE IF EXISTS tmpOrders\";"
+					+ " PREPARE stmt FROM @sql;"
+					+ " EXECUTE stmt;"
+					+ " DEALLOCATE PREPARE stmt;"
+					+ "\nSET @sql = \"CREATE TEMPORARY TABLE tmpOrders SELECT id, 100 AS Income FROM
tblTestBug2297_1 GROUP BY id\";"
+					+ " PREPARE stmt FROM @sql;"
+					+ " EXECUTE stmt;"
+					+ " DEALLOCATE PREPARE stmt;"
+					+ "\n SELECT id, Income FROM (SELECT e.id AS id ,COALESCE(prof.Income,0) AS Income"
+					+ "\n FROM tblTestBug2297_2 e LEFT JOIN tmpOrders prof ON e.id = prof.id"
+					+ "\n WHERE e.CreatedOn > '2006-08-01') AS Final ORDER BY id;" 
+					+ "\nEND");
+	
+			this.stmt.executeUpdate("INSERT INTO tblTestBug2297_1 (`id`,`Income`) VALUES "
+					+ "('a',4094.00),"
+					+ "('b',500.00),"
+					+ "('c',3462.17),"
+					+ " ('d',500.00),"
+					+ " ('e',600.00)");
+			
+			this.stmt.executeUpdate("INSERT INTO tblTestBug2297_2 (`id`,`CreatedOn`) VALUES "
+					+ "('d','2006-08-31 00:00:00'),"
+					+ "('e','2006-08-31 00:00:00'),"
+				+ "('b','2006-08-31 00:00:00'),"
+				+ "('c','2006-08-31 00:00:00'),"
+				+ "('a','2006-08-31 00:00:00')");
+			
+			try {
+				this.pstmt = this.conn.prepareStatement("{CALL testBug22297(?)}");
+				this.pstmt.setInt(1, 1);
+				this.rs =this.pstmt.executeQuery();
+	            
+				String[] ids = new String[] { "a", "b", "c", "d", "e"};
+	            int pos = 0;
+	            
+	            while (this.rs.next()) {
+	            	assertEquals(ids[pos++], rs.getString(1));
+	            	assertEquals(100, rs.getInt(2));
+	            }
+
+                assertEquals(this.pstmt.getClass().getName(),
+                		com.mysql.jdbc.PreparedStatement.class.getName());
+			} finally {
+				closeMemberJDBCResources();
+			}
+		}
+	}
 }

Modified: trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java
===================================================================
--- trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java	2006-09-19
01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/testsuite/regression/ConnectionRegressionTest.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -1457,7 +1457,9 @@
 				for (int j = 0; j < 2; j++) {
 					for (int i = 0; i < getMethods.length; i++) {
 						if (getMethods[i].getName().startsWith("get")
-								&& !getMethods[i].getName().equals("getURL")) {
+								&& !getMethods[i].getName().equals("getURL")
+								&& !getMethods[i].getName().equals("getRowId")
+								&& !getMethods[i].getName().equals("getSQLXML()")) {
 							Class[] parameterTypes = getMethods[i]
 									.getParameterTypes();
 

Modified: trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java
===================================================================
--- trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java	2006-09-19
01:45:03 UTC (rev 5748)
+++ trunk/connector-j/src/testsuite/regression/StatementRegressionTest.java	2006-09-19
01:47:23 UTC (rev 5749)
@@ -60,6 +60,7 @@
 
 import com.mysql.jdbc.SQLError;
 import com.mysql.jdbc.ServerPreparedStatement;
+import com.mysql.jdbc.exceptions.MySQLTimeoutException;
 
 /**
  * Regression tests for the Statement class
@@ -3398,4 +3399,40 @@
 			closeMemberJDBCResources();
 		}
 	}
+
+	/**
+	 * Tests fix for BUG#22359 - Driver was using millis for
+	 * Statement.setQueryTimeout() when spec says argument is
+	 * seconds.
+	 * 
+	 * @throws Exception if the test fails.
+	 */
+	public void testBug22359() throws Exception {
+		if (versionMeetsMinimum(5, 0)) {
+			Statement timeoutStmt = null;
+			
+			try {
+				timeoutStmt = this.conn.createStatement();
+				timeoutStmt.setQueryTimeout(2);
+				
+				long begin = System.currentTimeMillis();
+				
+				try {
+					timeoutStmt.execute("SELECT SLEEP(30)");
+				} catch (MySQLTimeoutException timeoutEx) {
+					long end = System.currentTimeMillis();
+					
+					assertTrue((end - begin) > 1000);
+				} catch (com.mysql.jdbc.exceptions.jdbc4.MySQLTimeoutException timeoutEx) {
+					long end = System.currentTimeMillis();
+					
+					assertTrue((end - begin) > 1000);
+				} 
+			} finally {
+				if (timeoutStmt != null) {
+					timeoutStmt.close();
+				}
+			}
+		}
+	}
 }

Modified: trunk/connector-j/src/testsuite/simple/StatementsTest.java
===================================================================
--- trunk/connector-j/src/testsuite/simple/StatementsTest.java	2006-09-19 01:45:03 UTC
(rev 5748)
+++ trunk/connector-j/src/testsuite/simple/StatementsTest.java	2006-09-19 01:47:23 UTC
(rev 5749)
@@ -27,8 +27,10 @@
 import java.io.ByteArrayInputStream;
 import java.io.CharArrayReader;
 import java.io.Reader;
+import java.io.StringReader;
 import java.sql.CallableStatement;
 import java.sql.Connection;
+import java.sql.NClob;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -532,7 +534,7 @@
 				cancelConn = getConnectionWithProps(null);
 				final Statement cancelStmt = cancelConn.createStatement();
 			
-				cancelStmt.setQueryTimeout(10);
+				cancelStmt.setQueryTimeout(1);
 	
 				long begin = System.currentTimeMillis();
 	
@@ -591,7 +593,7 @@
 				
 				final PreparedStatement cancelPstmt = cancelConn.prepareStatement("SELECT
SLEEP(30)");
 				
-				cancelPstmt.setQueryTimeout(10);
+				cancelPstmt.setQueryTimeout(1);
 	
 				begin = System.currentTimeMillis();
 	
@@ -650,7 +652,7 @@
 				
 				final PreparedStatement cancelClientPstmt =
((com.mysql.jdbc.Connection)cancelConn).clientPrepareStatement("SELECT SLEEP(30)");
 				
-				cancelClientPstmt.setQueryTimeout(10);
+				cancelClientPstmt.setQueryTimeout(1);
 	
 				begin = System.currentTimeMillis();
 	
@@ -1536,4 +1538,582 @@
 		}
 
 	}
+
+	/**
+	 * Tests for ResultSet.getNCharacterStream()
+	 * 
+	 * @throws Exception
+	 */
+	public void testGetNCharacterSteram() throws Exception {
+	    createTable("testGetNCharacterStream", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10))");
+	    this.stmt.executeUpdate("INSERT INTO testGetNCharacterStream (c1, c2) VALUES (_utf8
'aaa', _utf8 'bbb')");
+	    this.rs = this.stmt.executeQuery("SELECT c1, c2 FROM testGetNCharacterStream");
+	    this.rs.next();
+	    char[] c1 = new char[3];
+	    this.rs.getNCharacterStream(1).read(c1);
+	    assertEquals("aaa", new String(c1));
+	    char[] c2 = new char[3];
+	    this.rs.getNCharacterStream("c2").read(c2);
+	    assertEquals("bbb", new String(c2));
+	    this.rs.close();
+	}
+
+	/**
+	 * Tests for ResultSet.getNClob()
+	 * 
+	 * @throws Exception
+	 */
+	public void testGetNClob() throws Exception {
+	    createTable("testGetNClob", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10))");
+	    this.stmt.executeUpdate("INSERT INTO testGetNClob (c1, c2) VALUES (_utf8 'aaa',
_utf8 'bbb')");
+	    this.rs = this.stmt.executeQuery("SELECT c1, c2 FROM testGetNClob");
+	    this.rs.next();
+	    char[] c1 = new char[3];
+	    this.rs.getNClob(1).getCharacterStream().read(c1);
+	    assertEquals("aaa", new String(c1));
+	    char[] c2 = new char[3];
+	    this.rs.getNClob("c2").getCharacterStream().read(c2);
+	    assertEquals("bbb", new String(c2));
+	    this.rs.close();
+	    
+	    // for isBinaryEncoded = true, using PreparedStatement
+	    createTable("testGetNClob", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10))");
+	    this.stmt.executeUpdate("INSERT INTO testGetNClob (c1, c2) VALUES (_utf8 'aaa',
_utf8 'bbb')");
+	    this.pstmt = this.conn.prepareStatement("SELECT c1, c2 FROM testGetNClob");
+	    this.rs = this.pstmt.executeQuery();
+	    this.rs.next();
+	    c1 = new char[3];
+	    this.rs.getNClob(1).getCharacterStream().read(c1);
+	    assertEquals("aaa", new String(c1));
+	    c2 = new char[3];
+	    this.rs.getNClob("c2").getCharacterStream().read(c2);
+	    assertEquals("bbb", new String(c2));
+	    this.rs.close();
+	}
+
+	/**
+	 * Tests for ResultSet.getNString()
+	 * 
+	 * @throws Exception
+	 */
+	public void testGetNString() throws Exception {
+	    createTable("testGetNString", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10))");
+	    this.stmt.executeUpdate("INSERT INTO testGetNString (c1, c2) VALUES (_utf8 'aaa',
_utf8 'bbb')");
+	    this.rs = this.stmt.executeQuery("SELECT c1, c2 FROM testGetNString");
+	    this.rs.next();
+	    assertEquals("aaa", this.rs.getNString(1));
+	    assertEquals("bbb", this.rs.getNString("c2"));
+	    this.rs.close();
+	}
+
+	/**
+	 * Tests for PreparedStatement.setNCharacterSteam()
+	 * 
+	 * @throws Exception
+	 */
+	public void testSetNCharacterStream() throws Exception {
+	    // suppose sql_mode don't include "NO_BACKSLASH_ESCAPES"
+	    
+	    createTable("testSetNCharacterStream", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10), " +
+	            "c3 NATIONAL CHARACTER(10))");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "false"); // use client-side prepared statement
+	    props1.put("useUnicode", "true");
+	    props1.put("characterEncoding", "latin1"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    com.mysql.jdbc.PreparedStatement pstmt1 = (com.mysql.jdbc.PreparedStatement)
+	        conn1.prepareStatement("INSERT INTO testSetNCharacterStream (c1, c2, c3) VALUES
(?, ?, ?)");
+	    pstmt1.setNCharacterStream(1, null, 0);
+	    pstmt1.setNCharacterStream(2, new StringReader("aaa"), 3);
+	    pstmt1.setNCharacterStream(3, new StringReader("\'aaa\'"), 5);
+	    pstmt1.execute();
+	    ResultSet rs1 = this.stmt.executeQuery("SELECT c1, c2, c3 FROM
testSetNCharacterStream");
+	    rs1.next();
+	    assertEquals(null, rs1.getString(1));
+	    assertEquals("aaa", rs1.getString(2));
+	    assertEquals("\'aaa\'", rs1.getString(3));
+	    rs1.close();
+	    pstmt1.close();
+	    conn1.close();
+	    
+	    createTable("testSetNCharacterStream", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10), " +
+	    "c3 NATIONAL CHARACTER(10))");
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "false"); // use client-side prepared statement
+	    props2.put("useUnicode", "true");
+	    props2.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    com.mysql.jdbc.PreparedStatement pstmt2 = (com.mysql.jdbc.PreparedStatement)
+	        conn2.prepareStatement("INSERT INTO testSetNCharacterStream (c1, c2, c3) VALUES
(?, ?, ?)");
+	    pstmt2.setNCharacterStream(1, null, 0);
+	    pstmt2.setNCharacterStream(2, new StringReader("aaa"), 3);
+	    pstmt2.setNCharacterStream(3, new StringReader("\'aaa\'"), 5);
+	    pstmt2.execute();
+	    ResultSet rs2 = this.stmt.executeQuery("SELECT c1, c2, c3 FROM
testSetNCharacterStream");
+	    rs2.next();
+	    assertEquals(null, rs2.getString(1));
+	    assertEquals("aaa", rs2.getString(2));
+	    assertEquals("\'aaa\'", rs2.getString(3));
+	    rs2.close();
+	    pstmt2.close();
+	    conn2.close();
+	}
+
+	/**
+	 * Tests for ServerPreparedStatement.setNCharacterSteam()
+	 * 
+	 * @throws Exception
+	 */
+	public void testSetNCharacterStreamServer() throws Exception {
+	    createTable("testSetNCharacterStreamServer", "(c1 NATIONAL CHARACTER(10))");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props1.put("useUnicode", "true");
+	    props1.put("characterEncoding", "latin1"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    com.mysql.jdbc.ServerPreparedStatement pstmt1 =
(com.mysql.jdbc.ServerPreparedStatement)
+	        conn1.prepareStatement("INSERT INTO testSetNCharacterStreamServer (c1) VALUES
(?)");
+	    try {
+	        pstmt1.setNCharacterStream(1, new StringReader("aaa"), 3);
+	        fail();
+	    } catch (SQLException e) {
+	        // ok
+	        assertEquals("Can not call setNCharacterStream() when connection character set
isn't UTF-8",
+	            e.getMessage());  
+	    }
+	    pstmt1.close();
+	    conn1.close();
+	    
+	    createTable("testSetNCharacterStreamServer", "(c1 LONGTEXT charset utf8)");
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props2.put("useUnicode", "true");
+	    props2.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    com.mysql.jdbc.ServerPreparedStatement pstmt2 =
(com.mysql.jdbc.ServerPreparedStatement)
+	        conn2.prepareStatement("INSERT INTO testSetNCharacterStreamServer (c1) VALUES
(?)");
+	    pstmt2.setNCharacterStream(1, new StringReader(
+	            new String(new char[81921])), 81921); // 10 Full Long Data Packet's chars +
1 char
+	    pstmt2.execute();
+	    ResultSet rs2 = this.stmt.executeQuery("SELECT c1 FROM
testSetNCharacterStreamServer");
+	    rs2.next();
+	    assertEquals(new String(new char[81921]), rs2.getString(1));
+	    rs2.close();
+	    pstmt2.close();
+	    conn2.close();
+	}
+
+	/**
+	 * Tests for PreparedStatement.setNClob()
+	 * 
+	 * @throws Exception
+	 */
+	public void testSetNClob() throws Exception {
+	    // suppose sql_mode don't include "NO_BACKSLASH_ESCAPES"
+	    
+	    createTable("testSetNClob", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL CHARACTER(10),
" +
+	            "c3 NATIONAL CHARACTER(10))");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "false"); // use client-side prepared statement
+	    props1.put("useUnicode", "true");
+	    props1.put("characterEncoding", "latin1"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    com.mysql.jdbc.PreparedStatement pstmt1 = (com.mysql.jdbc.PreparedStatement)
+	        conn1.prepareStatement("INSERT INTO testSetNClob (c1, c2, c3) VALUES (?, ?,
?)");
+	    pstmt1.setNClob(1, (NClob)null);
+	    NClob nclob2 = conn1.createNClob();
+	    nclob2.setString(1, "aaa");
+	    pstmt1.setNClob(2, nclob2);                   // for setNClob(int, NClob)
+	    Reader reader3 = new StringReader("\'aaa\'");
+	    pstmt1.setNClob(3, reader3, 5);               // for setNClob(int, Reader, long)
+	    pstmt1.execute();
+	    ResultSet rs1 = this.stmt.executeQuery("SELECT c1, c2, c3 FROM testSetNClob");
+	    rs1.next();
+	    assertEquals(null, rs1.getString(1));
+	    assertEquals("aaa", rs1.getString(2));
+	    assertEquals("\'aaa\'", rs1.getString(3));
+	    rs1.close();
+	    pstmt1.close();
+	    conn1.close();
+	    
+	    createTable("testSetNClob", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL CHARACTER(10),
" +
+	    "c3 NATIONAL CHARACTER(10))");
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "false"); // use client-side prepared statement
+	    props2.put("useUnicode", "true");
+	    props2.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    com.mysql.jdbc.PreparedStatement pstmt2 = (com.mysql.jdbc.PreparedStatement)
+	        conn2.prepareStatement("INSERT INTO testSetNClob (c1, c2, c3) VALUES (?, ?,
?)");
+	    pstmt2.setNClob(1, (NClob)null);
+	    nclob2 = conn2.createNClob();
+	    nclob2.setString(1, "aaa");
+	    pstmt2.setNClob(2, nclob2);             // for setNClob(int, NClob)
+	    reader3 = new StringReader("\'aaa\'");
+	    pstmt2.setNClob(3, reader3, 5);         // for setNClob(int, Reader, long)
+	    pstmt2.execute();
+	    ResultSet rs2 = this.stmt.executeQuery("SELECT c1, c2, c3 FROM testSetNClob");
+	    rs2.next();
+	    assertEquals(null, rs2.getString(1));
+	    assertEquals("aaa", rs2.getString(2));
+	    assertEquals("\'aaa\'", rs2.getString(3));
+	    rs2.close();
+	    pstmt2.close();
+	    conn2.close();
+	}
+
+	/**
+	 * Tests for ServerPreparedStatement.setNClob()
+	 * 
+	 * @throws Exception
+	 */
+	public void testSetNClobServer() throws Exception {
+	    createTable("testSetNClobServer", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10))");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props1.put("useUnicode", "true");
+	    props1.put("characterEncoding", "latin1"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    com.mysql.jdbc.ServerPreparedStatement pstmt1 =
(com.mysql.jdbc.ServerPreparedStatement)
+	        conn1.prepareStatement("INSERT INTO testSetNClobServer (c1, c2) VALUES (?, ?)");
+	    NClob nclob1 = conn1.createNClob();
+	    nclob1.setString(1, "aaa");
+	    Reader reader2 = new StringReader("aaa");
+	    try {
+	        pstmt1.setNClob(1, nclob1);
+	        fail();
+	    } catch (SQLException e) {
+	        // ok
+	        assertEquals("Can not call setNClob() when connection character set isn't
UTF-8",
+	            e.getMessage());  
+	    }
+	    try {
+	        pstmt1.setNClob(2, reader2, 3);
+	        fail();
+	    } catch (SQLException e) {
+	        // ok
+	        assertEquals("Can not call setNClob() when connection character set isn't
UTF-8",
+	            e.getMessage());  
+	    }
+	    pstmt1.close();
+	    conn1.close();
+	    
+	    createTable("testSetNClobServer", "(c1 NATIONAL CHARACTER(10), c2 LONGTEXT charset
utf8)");
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props2.put("useUnicode", "true");
+	    props2.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    com.mysql.jdbc.ServerPreparedStatement pstmt2 =
(com.mysql.jdbc.ServerPreparedStatement)
+	        conn2.prepareStatement("INSERT INTO testSetNClobServer (c1, c2) VALUES (?, ?)");
+	    nclob1 = conn2.createNClob();
+	    nclob1.setString(1, "aaa");
+	    pstmt2.setNClob(1, nclob1);
+	    pstmt2.setNClob(2, new StringReader(
+	            new String(new char[81921])), 81921); // 10 Full Long Data Packet's chars +
1 char
+	    pstmt2.execute();
+	    ResultSet rs2 = this.stmt.executeQuery("SELECT c1, c2 FROM testSetNClobServer");
+	    rs2.next();
+	    assertEquals("aaa", rs2.getString(1));
+	    assertEquals(new String(new char[81921]), rs2.getString(2));
+	    rs2.close();
+	    pstmt2.close();
+	    conn2.close();
+	}
+
+	/**
+	 * Tests for PreparedStatement.setNString()
+	 * 
+	 * @throws Exception
+	 */
+	public void testSetNString() throws Exception {
+	    // suppose sql_mode don't include "NO_BACKSLASH_ESCAPES"
+	    
+	    createTable("testSetNString", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10), " +
+	            "c3 NATIONAL CHARACTER(10)) DEFAULT CHARACTER SET cp932");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "false"); // use client-side prepared statement
+	    props1.put("useUnicode", "true");
+	    props1.put("characterEncoding", "MS932"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    com.mysql.jdbc.PreparedStatement pstmt1 = (com.mysql.jdbc.PreparedStatement)
+	        conn1.prepareStatement("INSERT INTO testSetNString (c1, c2, c3) VALUES (?, ?,
?)");
+	    pstmt1.setNString(1, null);
+	    pstmt1.setNString(2, "aaa");
+	    pstmt1.setNString(3, "\'aaa\'");
+	    pstmt1.execute();
+	    ResultSet rs1 = this.stmt.executeQuery("SELECT c1, c2, c3 FROM testSetNString");
+	    rs1.next();
+	    assertEquals(null, rs1.getString(1));
+	    assertEquals("aaa", rs1.getString(2));
+	    assertEquals("\'aaa\'", rs1.getString(3));
+	    rs1.close();
+	    pstmt1.close();
+	    conn1.close();
+	    
+	    createTable("testSetNString", "(c1 NATIONAL CHARACTER(10), c2 NATIONAL
CHARACTER(10), " +
+	    "c3 NATIONAL CHARACTER(10)) DEFAULT CHARACTER SET cp932");
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "false"); // use client-side prepared statement
+	    props2.put("useUnicode", "true");
+	    props2.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    com.mysql.jdbc.PreparedStatement pstmt2 = (com.mysql.jdbc.PreparedStatement)
+	        conn2.prepareStatement("INSERT INTO testSetNString (c1, c2, c3) VALUES (?, ?,
?)");
+	    pstmt2.setNString(1, null);
+	    pstmt2.setNString(2, "aaa");
+	    pstmt2.setNString(3, "\'aaa\'");
+	    pstmt2.execute();
+	    ResultSet rs2 = this.stmt.executeQuery("SELECT c1, c2, c3 FROM testSetNString");
+	    rs2.next();
+	    assertEquals(null, rs2.getString(1));
+	    assertEquals("aaa", rs2.getString(2));
+	    assertEquals("\'aaa\'", rs2.getString(3));
+	    rs2.close();
+	    pstmt2.close();
+	    conn2.close();
+	}
+
+	/**
+	 * Tests for ServerPreparedStatement.setNString()
+	 * 
+	 * @throws Exception
+	 */
+	public void testSetNStringServer() throws Exception {
+	    createTable("testSetNStringServer", "(c1 NATIONAL CHARACTER(10))");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props1.put("useUnicode", "true");
+	    props1.put("characterEncoding", "latin1"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    com.mysql.jdbc.ServerPreparedStatement pstmt1 =
(com.mysql.jdbc.ServerPreparedStatement)
+	        conn1.prepareStatement("INSERT INTO testSetNStringServer (c1) VALUES (?)");
+	    try {
+	        pstmt1.setNString(1, "aaa");
+	        fail();
+	    } catch (SQLException e) {
+	        // ok
+	        assertEquals("Can not call setNString() when connection character set isn't
UTF-8",
+	            e.getMessage());  
+	    }
+	    pstmt1.close();
+	    conn1.close();
+	    
+	    createTable("testSetNStringServer", "(c1 NATIONAL CHARACTER(10))");
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props2.put("useUnicode", "true");
+	    props2.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    com.mysql.jdbc.ServerPreparedStatement pstmt2 =
(com.mysql.jdbc.ServerPreparedStatement)
+	        conn2.prepareStatement("INSERT INTO testSetNStringServer (c1) VALUES (?)");
+	    pstmt2.setNString(1, "\'aaa\'");
+	    pstmt2.execute();
+	    ResultSet rs2 = this.stmt.executeQuery("SELECT c1 FROM testSetNStringServer");
+	    rs2.next();
+	    assertEquals("\'aaa\'", rs2.getString(1));
+	    rs2.close();
+	    pstmt2.close();
+	    conn2.close();
+	}
+
+	/**
+	 * Tests for ResultSet.updateNCharacterStream()
+	 * 
+	 * @throws Exception
+	 */
+	public void testUpdateNCharacterStream() throws Exception {
+	    createTable("testUpdateNCharacterStream", 
+	            "(c1 CHAR(10) PRIMARY KEY, c2 NATIONAL CHARACTER(10)) default character set
sjis");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props1.put("characterEncoding", "UTF-8"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    PreparedStatement pstmt1 = conn1.prepareStatement(
+	            "INSERT INTO testUpdateNCharacterStream (c1, c2) VALUES (?, ?)");
+	    pstmt1.setString(1, "1");
+	    pstmt1.setNCharacterStream(2, new StringReader("aaa"), 3);
+	    pstmt1.execute();
+	    Statement stmt1 = conn1.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
+	    ResultSet rs1 = stmt1.executeQuery("SELECT c1, c2 FROM testUpdateNCharacterStream");
+	    rs1.next();
+	    rs1.updateNCharacterStream("c2", new StringReader("bbb"), 3);
+	    rs1.updateRow();
+	    rs1.moveToInsertRow();
+	    rs1.updateString("c1", "2");
+	    rs1.updateNCharacterStream("c2", new StringReader("ccc"), 3);
+	    rs1.insertRow();
+	    ResultSet rs2 = stmt1.executeQuery("SELECT c1, c2 FROM testUpdateNCharacterStream");
+	    rs2.next();
+	    assertEquals("1", rs2.getString("c1"));
+	    assertEquals("bbb", rs2.getNString("c2"));
+	    rs2.next();
+	    assertEquals("2", rs2.getString("c1"));
+	    assertEquals("ccc", rs2.getNString("c2"));
+	    pstmt1.close();
+	    stmt1.close();
+	    conn1.close();
+	    
+	    createTable("testUpdateNCharacterStream", 
+	            "(c1 CHAR(10) PRIMARY KEY, c2 CHAR(10)) default character set sjis"); //
sjis field
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props2.put("characterEncoding", "SJIS"); // ensure charset isn't utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    PreparedStatement pstmt2 = conn2.prepareStatement(
+	            "INSERT INTO testUpdateNCharacterStream (c1, c2) VALUES (?, ?)");
+	    pstmt2.setString(1, "1");
+	    pstmt2.setString(2, "aaa");
+	    pstmt2.execute();
+	    Statement stmt2 = conn2.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
+	    ResultSet rs3 = stmt2.executeQuery("SELECT c1, c2 FROM testUpdateNCharacterStream");
+	    rs3.next();
+	    try {
+	        rs3.updateNCharacterStream("c2", new StringReader("bbb"), 3); // field's charset
isn't utf8
+	        fail();
+	    } catch (SQLException ex) {
+	        assertEquals("Can not call updateNCharacterStream() when field's character set
isn't UTF-8",
+	                ex.getMessage());
+	    }
+	    rs3.close();
+	    pstmt2.close();
+	    stmt2.close();
+	    conn2.close();  
+	}
+
+	/**
+	 * Tests for ResultSet.updateNClob()
+	 * 
+	 * @throws Exception
+	 */
+	public void testUpdateNClob() throws Exception {
+	    createTable("testUpdateNChlob", 
+	            "(c1 CHAR(10) PRIMARY KEY, c2 NATIONAL CHARACTER(10)) default character set
sjis");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props1.put("characterEncoding", "UTF-8"); // ensure charset isn't utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    PreparedStatement pstmt1 = conn1.prepareStatement(
+	            "INSERT INTO testUpdateNChlob (c1, c2) VALUES (?, ?)");
+	    pstmt1.setString(1, "1");
+	    NClob nClob1 = conn1.createNClob();
+	    nClob1.setString(1, "aaa");
+	    pstmt1.setNClob(2, nClob1);
+	    pstmt1.execute();
+	    Statement stmt1 = conn1.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
+	    ResultSet rs1 = stmt1.executeQuery("SELECT c1, c2 FROM testUpdateNChlob");
+	    rs1.next();
+	    NClob nClob2 = conn1.createNClob();
+	    nClob2.setString(1, "bbb");
+	    rs1.updateNClob("c2", nClob2);
+	    rs1.updateRow();
+	    rs1.moveToInsertRow();
+	    rs1.updateString("c1", "2");
+	    NClob nClob3 = conn1.createNClob();
+	    nClob3.setString(1, "ccc");
+	    rs1.updateNClob("c2", nClob3);
+	    rs1.insertRow();
+	    ResultSet rs2 = stmt1.executeQuery("SELECT c1, c2 FROM testUpdateNChlob");
+	    rs2.next();
+	    assertEquals("1", rs2.getString("c1"));
+	    assertEquals("bbb", rs2.getNString("c2"));
+	    rs2.next();
+	    assertEquals("2", rs2.getString("c1"));
+	    assertEquals("ccc", rs2.getNString("c2"));
+	    pstmt1.close();
+	    stmt1.close();
+	    conn1.close();
+	    
+	    createTable("testUpdateNChlob", 
+	            "(c1 CHAR(10) PRIMARY KEY, c2 CHAR(10)) default character set sjis"); //
sjis field
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props2.put("characterEncoding", "SJIS"); // ensure charset isn't utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    PreparedStatement pstmt2 = conn2.prepareStatement(
+	            "INSERT INTO testUpdateNChlob (c1, c2) VALUES (?, ?)");
+	    pstmt2.setString(1, "1");
+	    pstmt2.setString(2, "aaa");
+	    pstmt2.execute();
+	    Statement stmt2 = conn2.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
+	    ResultSet rs3 = stmt2.executeQuery("SELECT c1, c2 FROM testUpdateNChlob");
+	    rs3.next();
+	    NClob nClob4 = conn2.createNClob();
+	    nClob4.setString(1, "bbb");
+	    try {
+	        rs3.updateNClob("c2", nClob4); // field's charset isn't utf8
+	        fail();
+	    } catch (SQLException ex) {
+	        assertEquals("Can not call updateNClob() when field's character set isn't
UTF-8",
+	                ex.getMessage());
+	    }
+	    rs3.close();
+	    pstmt2.close();
+	    stmt2.close();
+	    conn2.close();  
+	}
+
+	/**
+	 * Tests for ResultSet.updateNString()
+	 * 
+	 * @throws Exception
+	 */
+	public void testUpdateNString() throws Exception {
+	    createTable("testUpdateNString", 
+	            "(c1 CHAR(10) PRIMARY KEY, c2 NATIONAL CHARACTER(10)) default character set
sjis");
+	    Properties props1 = new Properties();
+	    props1.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props1.put("characterEncoding", "UTF-8"); // ensure charset is utf8 here
+	    Connection conn1 = getConnectionWithProps(props1);
+	    PreparedStatement pstmt1 = conn1.prepareStatement(
+	            "INSERT INTO testUpdateNString (c1, c2) VALUES (?, ?)");
+	    pstmt1.setString(1, "1");
+	    pstmt1.setNString(2, "aaa");
+	    pstmt1.execute();
+	    Statement stmt1 = conn1.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
+	    ResultSet rs1 = stmt1.executeQuery("SELECT c1, c2 FROM testUpdateNString");
+	    rs1.next();
+	    rs1.updateNString("c2", "bbb");
+	    rs1.updateRow();
+	    rs1.moveToInsertRow();
+	    rs1.updateString("c1", "2");
+	    rs1.updateNString("c2", "ccc");
+	    rs1.insertRow();
+	    ResultSet rs2 = stmt1.executeQuery("SELECT c1, c2 FROM testUpdateNString");
+	    rs2.next();
+	    assertEquals("1", rs2.getString("c1"));
+	    assertEquals("bbb", rs2.getNString("c2"));
+	    rs2.next();
+	    assertEquals("2", rs2.getString("c1"));
+	    assertEquals("ccc", rs2.getNString("c2"));
+	    pstmt1.close();
+	    stmt1.close();
+	    conn1.close();
+	    
+	    createTable("testUpdateNString", 
+	            "(c1 CHAR(10) PRIMARY KEY, c2 CHAR(10)) default character set sjis"); //
sjis field
+	    Properties props2 = new Properties();
+	    props2.put("useServerPrepStmts", "true"); // use server-side prepared statement
+	    props2.put("characterEncoding", "SJIS"); // ensure charset isn't utf8 here
+	    Connection conn2 = getConnectionWithProps(props2);
+	    PreparedStatement pstmt2 = conn2.prepareStatement(
+	            "INSERT INTO testUpdateNString (c1, c2) VALUES (?, ?)");
+	    pstmt2.setString(1, "1");
+	    pstmt2.setString(2, "aaa");
+	    pstmt2.execute();
+	    Statement stmt2 = conn2.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
+	    ResultSet rs3 = stmt2.executeQuery("SELECT c1, c2 FROM testUpdateNString");
+	    rs3.next();
+	    try {
+	        rs3.updateNString("c2", "bbb"); // field's charset isn't utf8
+	        fail();
+	    } catch (SQLException ex) {
+	        assertEquals("Can not call updateNString() when field's character set isn't
UTF-8",
+	                ex.getMessage());
+	    }
+	    rs3.close();
+	    pstmt2.close();
+	    stmt2.close();
+	    conn2.close();      
+	}
 }

Thread
Connector/J commit: r5749 - in trunk/connector-j: . src/com/mysql/jdbc src/com/mysql/jdbc/exceptions src/com/mysql/jdbc/exceptions/jdbc4 src/com/mysql...mmatthews19 Sep