提交 cc1352c7 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Use MySQL-compatible conversion between CHAR and BINARY in MySQL mode

上级 bbf4df6f
...@@ -186,6 +186,11 @@ public class Mode { ...@@ -186,6 +186,11 @@ public class Mode {
*/ */
public boolean allowDB2TimestampFormat; public boolean allowDB2TimestampFormat;
/**
* Convert (VAR)CHAR to VAR(BINARY) and vice versa with UTF-8 encoding instead of HEX.
*/
public boolean charToBinaryInUtf8;
/** /**
* An optional Set of hidden/disallowed column types. * An optional Set of hidden/disallowed column types.
* Certain DBMSs don't support all column types provided by H2, such as * Certain DBMSs don't support all column types provided by H2, such as
...@@ -269,6 +274,7 @@ public class Mode { ...@@ -269,6 +274,7 @@ public class Mode {
mode.supportedClientInfoPropertiesRegEx = mode.supportedClientInfoPropertiesRegEx =
Pattern.compile(".*"); Pattern.compile(".*");
mode.prohibitEmptyInPredicate = true; mode.prohibitEmptyInPredicate = true;
mode.charToBinaryInUtf8 = true;
add(mode); add(mode);
mode = new Mode(ModeEnum.Oracle); mode = new Mode(ModeEnum.Oracle);
......
...@@ -1065,7 +1065,7 @@ public class JdbcResultSet extends TraceObject implements ResultSet, JdbcResultS ...@@ -1065,7 +1065,7 @@ public class JdbcResultSet extends TraceObject implements ResultSet, JdbcResultS
public byte[] getBytes(int columnIndex) throws SQLException { public byte[] getBytes(int columnIndex) throws SQLException {
try { try {
debugCodeCall("getBytes", columnIndex); debugCodeCall("getBytes", columnIndex);
return get(columnIndex).getBytes(); return get(columnIndex).convertTo(Value.BYTES, -1, conn.getMode()).getBytes();
} catch (Exception e) { } catch (Exception e) {
throw logAndConvert(e); throw logAndConvert(e);
} }
......
...@@ -957,6 +957,33 @@ public abstract class Value { ...@@ -957,6 +957,33 @@ public abstract class Value {
} }
break; break;
} }
case STRING: {
String s;
if (getType() == BYTES && mode != null && mode.charToBinaryInUtf8) {
s = new String(getBytesNoCopy());
} else {
s = getString();
}
return ValueString.get(s);
}
case STRING_IGNORECASE: {
String s;
if (getType() == BYTES && mode != null && mode.charToBinaryInUtf8) {
s = new String(getBytesNoCopy());
} else {
s = getString();
}
return ValueStringIgnoreCase.get(s);
}
case STRING_FIXED: {
String s;
if (getType() == BYTES && mode != null && mode.charToBinaryInUtf8) {
s = new String(getBytesNoCopy());
} else {
s = getString();
}
return ValueStringFixed.get(s, precision, mode);
}
case JAVA_OBJECT: { case JAVA_OBJECT: {
switch (getType()) { switch (getType()) {
case BYTES: case BYTES:
...@@ -1081,17 +1108,11 @@ public abstract class Value { ...@@ -1081,17 +1108,11 @@ public abstract class Value {
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
return ValueTimestampTimeZone.parse(s.trim()); return ValueTimestampTimeZone.parse(s.trim());
case BYTES: case BYTES:
return ValueBytes.getNoCopy( return ValueBytes.getNoCopy(mode != null && mode.charToBinaryInUtf8 ?
StringUtils.convertHexToBytes(s.trim())); s.getBytes(StandardCharsets.UTF_8): StringUtils.convertHexToBytes(s.trim()));
case JAVA_OBJECT: case JAVA_OBJECT:
return ValueJavaObject.getNoCopy(null, return ValueJavaObject.getNoCopy(null,
StringUtils.convertHexToBytes(s.trim()), getDataHandler()); StringUtils.convertHexToBytes(s.trim()), getDataHandler());
case STRING:
return ValueString.get(s);
case STRING_IGNORECASE:
return ValueStringIgnoreCase.get(s);
case STRING_FIXED:
return ValueStringFixed.get(s, precision, mode);
case DOUBLE: case DOUBLE:
return ValueDouble.get(Double.parseDouble(s.trim())); return ValueDouble.get(Double.parseDouble(s.trim()));
case FLOAT: case FLOAT:
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
package org.h2.test.db; package org.h2.test.db;
import java.nio.charset.StandardCharsets;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
...@@ -304,6 +305,28 @@ public class TestCompatibility extends TestBase { ...@@ -304,6 +305,28 @@ public class TestCompatibility extends TestBase {
// check the weird MySQL variant of DELETE // check the weird MySQL variant of DELETE
stat.execute("DELETE TEST FROM TEST WHERE 1=2"); stat.execute("DELETE TEST FROM TEST WHERE 1=2");
// Check conversion between VARCHAR and VARBINARY
String string = "ABCD\u1234";
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
stat.execute("CREATE TABLE TEST2(C VARCHAR, B VARBINARY)");
stat.execute("INSERT INTO TEST2(C) VALUES ('" + string + "')");
assertEquals(1, stat.executeUpdate("UPDATE TEST2 SET B = C"));
ResultSet rs = stat.executeQuery("SELECT B FROM TEST2");
assertTrue(rs.next());
assertEquals(bytes, rs.getBytes(1));
assertEquals(1, stat.executeUpdate("UPDATE TEST2 SET C = B"));
testMySQLBytesCheck(stat, string, bytes);
PreparedStatement prep = conn.prepareStatement("UPDATE TEST2 SET C = ?");
prep.setBytes(1, bytes);
assertEquals(1, prep.executeUpdate());
testMySQLBytesCheck(stat, string, bytes);
stat.execute("DELETE FROM TEST2");
prep = conn.prepareStatement("INSERT INTO TEST2(C) VALUES (?)");
prep.setBytes(1, bytes);
assertEquals(1, prep.executeUpdate());
testMySQLBytesCheck(stat, string, bytes);
stat.execute("DROP TABLE TEST2");
if (config.memory) { if (config.memory) {
return; return;
} }
...@@ -324,7 +347,7 @@ public class TestCompatibility extends TestBase { ...@@ -324,7 +347,7 @@ public class TestCompatibility extends TestBase {
stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE); ResultSet.CONCUR_UPDATABLE);
assertResult("test", stat, "SHOW TABLES"); assertResult("test", stat, "SHOW TABLES");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST"); rs = stat.executeQuery("SELECT * FROM TEST");
rs.next(); rs.next();
rs.updateString(2, "Hallo"); rs.updateString(2, "Hallo");
rs.updateRow(); rs.updateRow();
...@@ -391,6 +414,14 @@ public class TestCompatibility extends TestBase { ...@@ -391,6 +414,14 @@ public class TestCompatibility extends TestBase {
conn = getConnection("compatibility"); conn = getConnection("compatibility");
} }
private void testMySQLBytesCheck(Statement stat, String string, byte[] bytes) throws SQLException {
ResultSet rs;
rs = stat.executeQuery("SELECT C FROM TEST2");
assertTrue(rs.next());
assertEquals(string, rs.getString(1));
assertEquals(bytes, rs.getBytes(1));
}
private void testSybaseAndMSSQLServer() throws SQLException { private void testSybaseAndMSSQLServer() throws SQLException {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("SET MODE MSSQLServer"); stat.execute("SET MODE MSSQLServer");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论