Added:
trunk/connector-j/svnmerge-commit-message.txt
Modified:
trunk/connector-j/
trunk/connector-j/CHANGES
trunk/connector-j/src/com/mysql/jdbc/Field.java
trunk/connector-j/src/com/mysql/jdbc/LocalizedErrorMessages.properties
trunk/connector-j/src/testsuite/simple/CharsetTests.java
Log:
Merged from 5.1.
Property changes on: trunk/connector-j
___________________________________________________________________
Name: svn:ignore
- bin
build
dist
+ bin
build
dist
Name: svnmerge-integrated
- /branches/branch_5_0:1-6478 /branches/branch_5_0/connector-j:1-5567 /branches/branch_5_1:1-6477
+ /branches/branch_5_0:1-6478 /branches/branch_5_0/connector-j:1-5567 /branches/branch_5_1:1-6477,6480
Modified: trunk/connector-j/CHANGES
===================================================================
--- trunk/connector-j/CHANGES 2007-07-04 06:05:29 UTC (rev 6481)
+++ trunk/connector-j/CHANGES 2007-07-05 19:01:07 UTC (rev 6482)
@@ -1,6 +1,23 @@
# Changelog
# $Id$
+nn-nn-07 - Version 5.1.3 Beta
+ - Setting "useBlobToStoreUTF8OutsideBMP" to "true" tells the
+ driver to treat [MEDIUM/LONG]BLOB columns as [LONG]VARCHAR
+ columns holding text encoded in UTF-8 that has characters
+ outside the BMP (4-byte encodings), which MySQL server
+ can't handle natively.
+
+ Set "utf8OutsideBmpExcludedColumnNamePattern" to a regex so that
+ column names matching the given regex will still be treated
+ as BLOBs The regex must follow the patterns used for the
+ java.util.regex package. The default is to exclude no columns,
+ and include all columns.
+
+ Set "utf8OutsideBmpIncludedColumnNamePattern" to specify exclusion
+ rules to "utf8OutsideBmpExcludedColumnNamePattern". The regex must
+ follow the patterns used for the java.util.regex package.
+
06-29-07 - Version 5.1.2 Beta
- Setting the configuration property "rewriteBatchedStatements"
Modified: trunk/connector-j/src/com/mysql/jdbc/Field.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Field.java 2007-07-04 06:05:29 UTC (rev 6481)
+++ trunk/connector-j/src/com/mysql/jdbc/Field.java 2007-07-05 19:01:07 UTC (rev 6482)
@@ -27,6 +27,7 @@
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.sql.Types;
+import java.util.regex.PatternSyntaxException;
/**
* Field is a class used to describe fields in a ResultSet
@@ -159,8 +160,13 @@
if (this.mysqlType == MysqlDefs.FIELD_TYPE_BLOB) {
if (this.charsetIndex == 63 ||
!this.connection.versionMeetsMinimum(4, 1, 0)) {
- setBlobTypeBasedOnLength();
- this.sqlType = MysqlDefs.mysqlToJavaType(this.mysqlType);
+ if (this.connection.getUseBlobToStoreUTF8OutsideBMP()
+ && shouldSetupForUtf8StringInBlob()) {
+ setupForUtf8StringInBlob();
+ } else {
+ setBlobTypeBasedOnLength();
+ this.sqlType = MysqlDefs.mysqlToJavaType(this.mysqlType);
+ }
} else {
// *TEXT masquerading as blob
this.mysqlType = MysqlDefs.FIELD_TYPE_VAR_STRING;
@@ -276,6 +282,67 @@
}
}
+ private boolean shouldSetupForUtf8StringInBlob() throws SQLException {
+ String includePattern = this.connection
+ .getUtf8OutsideBmpIncludedColumnNamePattern();
+ String excludePattern = this.connection
+ .getUtf8OutsideBmpExcludedColumnNamePattern();
+
+ if (excludePattern != null
+ && !StringUtils.isEmptyOrWhitespaceOnly(excludePattern)) {
+ try {
+ if (getOriginalName().matches(excludePattern)) {
+ if (includePattern != null
+ && !StringUtils.isEmptyOrWhitespaceOnly(includePattern)) {
+ try {
+ if (getOriginalName().matches(includePattern)) {
+ return true;
+ }
+ } catch (PatternSyntaxException pse) {
+ SQLException sqlEx = SQLError
+ .createSQLException(
+ "Illegal regex specified for \"utf8OutsideBmpIncludedColumnNamePattern\"",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+
+ if (!this.connection.getParanoid()) {
+ sqlEx.initCause(pse);
+ }
+
+ throw sqlEx;
+ }
+ }
+
+ return false;
+ }
+ } catch (PatternSyntaxException pse) {
+ SQLException sqlEx = SQLError
+ .createSQLException(
+ "Illegal regex specified for \"utf8OutsideBmpExcludedColumnNamePattern\"",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+
+ if (!this.connection.getParanoid()) {
+ sqlEx.initCause(pse);
+ }
+
+ throw sqlEx;
+ }
+ }
+
+ return true;
+ }
+
+ private void setupForUtf8StringInBlob() {
+ if (this.length == MysqlDefs.LENGTH_TINYBLOB || this.length == MysqlDefs.LENGTH_BLOB) {
+ this.mysqlType = MysqlDefs.FIELD_TYPE_VARCHAR;
+ this.sqlType = Types.VARCHAR;
+ } else {
+ this.mysqlType = MysqlDefs.FIELD_TYPE_VAR_STRING;
+ this.sqlType = Types.LONGVARCHAR;
+ }
+
+ this.charsetIndex = 33;
+ }
+
/**
* Constructor used when communicating with pre 4.1 servers
*/
Modified: trunk/connector-j/src/com/mysql/jdbc/LocalizedErrorMessages.properties
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/LocalizedErrorMessages.properties 2007-07-04 06:05:29 UTC (rev 6481)
+++ trunk/connector-j/src/com/mysql/jdbc/LocalizedErrorMessages.properties 2007-07-05 19:01:07 UTC (rev 6482)
@@ -583,6 +583,9 @@
ConnectionProperties.trustCertificateKeyStorePassword=Password for the trusted root certificates KeyStore
ConnectionProperties.Username=The user to connect as
ConnectionProperties.Password=The password to use when connecting
+ConnectionProperties.useBlobToStoreUTF8OutsideBMP=Tells the driver to treat [MEDIUM/LONG]BLOB columns as [LONG]VARCHAR columns holding text encoded in UTF-8 that has characters outside the BMP (4-byte encodings), which MySQL server can't handle natively.
+ConnectionProperties.utf8OutsideBmpExcludedColumnNamePattern=When "useBlobToStoreUTF8OutsideBMP" is set to "true", column names matching the given regex will still be treated as BLOBs unless they match the regex specified for "utf8OutsideBmpIncludedColumnNamePattern". The regex must follow the patterns used for the java.util.regex package.
+ConnectionProperties.utf8OutsideBmpIncludedColumnNamePattern=Used to specify exclusion rules to "utf8OutsideBmpExcludedColumnNamePattern". The regex must follow the patterns used for the java.util.regex package.
#
# Error Messages for Connection Properties
Modified: trunk/connector-j/src/testsuite/simple/CharsetTests.java
===================================================================
--- trunk/connector-j/src/testsuite/simple/CharsetTests.java 2007-07-04 06:05:29 UTC (rev 6481)
+++ trunk/connector-j/src/testsuite/simple/CharsetTests.java 2007-07-05 19:01:07 UTC (rev 6482)
@@ -23,7 +23,9 @@
package testsuite.simple;
import java.sql.Connection;
+import java.sql.SQLException;
import java.sql.Statement;
+import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -290,4 +292,158 @@
}
}
}
+
+ public void testUtf8OutsideBMPInBlob() throws Exception {
+ createTable("utf8Test", "(include_blob BLOB, include_tinyblob TINYBLOB, include_longblob LONGBLOB, exclude_tinyblob TINYBLOB, exclude_blob BLOB, exclude_longblob LONGBLOB)");
+
+ // We know this gets truncated in MySQL currently, even though it's valid UTF-8, it's just 4 bytes encoded
+ String outsideBmp = new String(new byte[] {(byte) 0xF0, (byte) 0x90, (byte) 0x80, (byte) 0x80}, "UTF-8");
+ byte[] outsideBmpBytes = outsideBmp.getBytes("UTF-8");
+ System.out.println(outsideBmpBytes.length);
+
+ Connection utf8Conn = getConnectionWithProps("useBlobToStoreUTF8OutsideBMP=true, characterEncoding=UTF-8");
+
+ String insertStatement = "INSERT INTO utf8Test VALUES (?, ?, ?, ?, ?, ?)";
+
+ this.pstmt = utf8Conn.prepareStatement(insertStatement);
+
+ this.pstmt.setString(1, outsideBmp);
+ this.pstmt.setString(2, outsideBmp);
+ this.pstmt.setString(3, outsideBmp);
+ this.pstmt.setString(4, outsideBmp);
+ this.pstmt.setString(5, outsideBmp);
+ this.pstmt.setString(6, outsideBmp);
+ this.pstmt.executeUpdate();
+
+ String query = "SELECT include_blob, include_tinyblob, include_longblob, exclude_tinyblob, exclude_blob, exclude_longblob FROM utf8Test";
+ this.rs = utf8Conn.createStatement().executeQuery(query);
+ this.rs.next();
+
+ assertEquals(this.rs.getObject(1).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(2).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(3).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(4).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(5).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(6).toString(), outsideBmp);
+
+ assertEquals("java.lang.String", this.rs.getObject(1).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(1));
+ assertEquals(Types.VARCHAR, this.rs.getMetaData().getColumnType(1));
+
+ assertEquals("java.lang.String", this.rs.getObject(2).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(2));
+ assertEquals(Types.VARCHAR, this.rs.getMetaData().getColumnType(2));
+
+ assertEquals("java.lang.String", this.rs.getObject(3).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(3));
+ assertEquals(Types.LONGVARCHAR, this.rs.getMetaData().getColumnType(3));
+
+ assertEquals("java.lang.String", this.rs.getObject(4).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(4));
+ assertEquals(Types.VARCHAR, this.rs.getMetaData().getColumnType(4));
+
+ assertEquals("java.lang.String", this.rs.getObject(5).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(5));
+ assertEquals(Types.VARCHAR, this.rs.getMetaData().getColumnType(5));
+
+ assertEquals("java.lang.String", this.rs.getObject(6).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(6));
+ assertEquals(Types.LONGVARCHAR, this.rs.getMetaData().getColumnType(6));
+
+ utf8Conn = getConnectionWithProps("useBlobToStoreUTF8OutsideBMP=true, characterEncoding=UTF-8,utf8OutsideBmpIncludedColumnNamePattern=.*include.*,utf8OutsideBmpExcludedColumnNamePattern=.*blob");
+
+ this.rs = utf8Conn.createStatement().executeQuery(query);
+ this.rs.next();
+
+ // Should walk/talk like a string, encoded in utf-8 on the server (4-byte)
+ assertEquals(this.rs.getObject(1).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(2).toString(), outsideBmp);
+ assertEquals(this.rs.getObject(3).toString(), outsideBmp);
+
+ assertEquals("java.lang.String", this.rs.getObject(1).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(1));
+ assertEquals(Types.VARCHAR, this.rs.getMetaData().getColumnType(1));
+
+ assertEquals("java.lang.String", this.rs.getObject(2).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(2));
+ assertEquals(Types.VARCHAR, this.rs.getMetaData().getColumnType(2));
+
+ assertEquals("java.lang.String", this.rs.getObject(3).getClass().getName());
+ assertEquals("java.lang.String", this.rs.getMetaData().getColumnClassName(3));
+ assertEquals(Types.LONGVARCHAR, this.rs.getMetaData().getColumnType(3));
+
+ // These should be left as a blob, since it matches the exclusion regex
+ assertTrue(bytesAreSame(this.rs.getBytes(4), outsideBmpBytes));
+ assertEquals("[B", this.rs.getObject(4).getClass().getName());
+ assertEquals("[B", this.rs.getMetaData().getColumnClassName(4));
+ assertEquals(Types.VARBINARY, this.rs.getMetaData().getColumnType(4));
+
+ // Should behave types-wise just like BLOB, including LONGVARBINARY type mapping
+ assertTrue(bytesAreSame(this.rs.getBytes(5), outsideBmpBytes));
+ assertEquals("[B", this.rs.getObject(5).getClass().getName());
+ assertEquals("[B", this.rs.getMetaData().getColumnClassName(5));
+ assertEquals(Types.LONGVARBINARY, this.rs.getMetaData().getColumnType(5));
+
+ assertTrue(bytesAreSame(this.rs.getBytes(6), outsideBmpBytes));
+ assertEquals("[B", this.rs.getObject(6).getClass().getName());
+ assertEquals("[B", this.rs.getMetaData().getColumnClassName(6));
+ assertEquals(Types.LONGVARBINARY, this.rs.getMetaData().getColumnType(6));
+
+ //
+ // Check error handling
+ //
+
+ utf8Conn = getConnectionWithProps("useBlobToStoreUTF8OutsideBMP=true, characterEncoding=UTF-8,utf8OutsideBmpIncludedColumnNamePattern={{,utf8OutsideBmpExcludedColumnNamePattern={{");
+
+ try {
+ utf8Conn.createStatement().executeQuery(query);
+ fail("Expected an exception");
+ } catch (SQLException sqlEx) {
+ assertNotNull(sqlEx.getCause());
+ assertEquals("java.util.regex.PatternSyntaxException", sqlEx.getCause().getClass().getName());
+ }
+
+ utf8Conn = getConnectionWithProps("useBlobToStoreUTF8OutsideBMP=true, characterEncoding=UTF-8,utf8OutsideBmpIncludedColumnNamePattern={{,utf8OutsideBmpExcludedColumnNamePattern=.*");
+
+ try {
+ utf8Conn.createStatement().executeQuery(query);
+ fail("Expected an exception");
+ } catch (SQLException sqlEx) {
+ assertNotNull(sqlEx.getCause());
+ assertEquals("java.util.regex.PatternSyntaxException", sqlEx.getCause().getClass().getName());
+ }
+
+ utf8Conn = getConnectionWithProps("useBlobToStoreUTF8OutsideBMP=true, characterEncoding=UTF-8,utf8OutsideBmpIncludedColumnNamePattern={{,utf8OutsideBmpExcludedColumnNamePattern={{,paranoid=true");
+
+ try {
+ utf8Conn.createStatement().executeQuery(query);
+ fail("Expected an exception");
+ } catch (SQLException sqlEx) {
+ assertNull(sqlEx.getCause());
+ }
+
+ utf8Conn = getConnectionWithProps("useBlobToStoreUTF8OutsideBMP=true, characterEncoding=UTF-8,utf8OutsideBmpIncludedColumnNamePattern={{,utf8OutsideBmpExcludedColumnNamePattern=.*,paranoid=true");
+
+ try {
+ utf8Conn.createStatement().executeQuery(query);
+ fail("Expected an exception");
+ } catch (SQLException sqlEx) {
+ assertNull(sqlEx.getCause());
+ }
+
+ }
+
+ private boolean bytesAreSame(byte[] byte1, byte[] byte2) {
+ if (byte1.length != byte2.length) {
+ return false;
+ }
+
+ for (int i = 0; i < byte1.length; i++) {
+ if (byte1[i] != byte2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
Added: trunk/connector-j/svnmerge-commit-message.txt
===================================================================
--- trunk/connector-j/svnmerge-commit-message.txt 2007-07-04 06:05:29 UTC (rev 6481)
+++ trunk/connector-j/svnmerge-commit-message.txt 2007-07-05 19:01:07 UTC (rev 6482)
@@ -0,0 +1,22 @@
+Merged revisions 6480 via svnmerge from
+svn+ssh://mmatthews@stripped/connectors-svnroot/connector-j/branches/branch_5_1
+
+........
+ r6480 | mmatthews | 2007-07-04 00:47:23 -0500 (Wed, 04 Jul 2007) | 15 lines
+
+ - Setting "useBlobToStoreUTF8OutsideBMP" to "true" tells the
+ driver to treat [MEDIUM/LONG]BLOB columns as [LONG]VARCHAR
+ columns holding text encoded in UTF-8 that has characters
+ outside the BMP (4-byte encodings), which MySQL server
+ can't handle natively.
+
+ Set "utf8OutsideBmpExcludedColumnNamePattern" to a regex so that
+ column names matching the given regex will still be treated
+ as BLOBs The regex must follow the patterns used for the
+ java.util.regex package. The default is to exclude no columns,
+ and include all columns.
+
+ Set "utf8OutsideBmpIncludedColumnNamePattern" to specify exclusion
+ rules to "utf8OutsideBmpExcludedColumnNamePattern". The regex must
+ follow the patterns used for the java.util.regex package.
+........
| Thread |
|---|
| • Connector/J commit: r6482 - in trunk/connector-j: . src/com/mysql/jdbc src/testsuite/simple | mmatthews | 5 Jul |