diff --git a/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java b/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java index f8dfc4a..eb2f7d2 100644 --- a/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java +++ b/src/main/java/com/jd/jdbc/vitess/VitessJdbcProperyUtil.java @@ -18,7 +18,9 @@ import com.jd.jdbc.common.Constant; import com.jd.jdbc.vitess.mysql.VitessPropertyKey; +import com.jd.jdbc.sqlparser.utils.StringUtils; import io.vitess.proto.Topodata; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -82,11 +84,25 @@ public static void checkServerTimezone(Properties info) { if (canonicalTimezone == null) { throw new IllegalArgumentException("serverTimezone is not found in jdbc url"); } - if (!"GMT".equalsIgnoreCase(canonicalTimezone) && TimeZone.getTimeZone(canonicalTimezone).getID().equals("GMT")) { + if (!"GMT".equalsIgnoreCase(canonicalTimezone) && "GMT".equals(TimeZone.getTimeZone(canonicalTimezone).getID())) { throw new IllegalArgumentException("invalid serverTimezone in jdbc url"); } } + public static void checkCharacterEncoding(Properties properties) { + String characterEncoding = properties.getProperty(VitessPropertyKey.characterEncoding.getKeyName()); + if (StringUtils.isEmpty(characterEncoding)) { + throw new IllegalArgumentException("characterEncoding is not found in jdbc url"); + } + String csn = Charset.defaultCharset().name(); + boolean characterEncodingFlag = "UTF-8".equalsIgnoreCase(characterEncoding) || "UTF8".equalsIgnoreCase(characterEncoding); + boolean csnFlag = "UTF-8".equalsIgnoreCase(csn); + if (characterEncodingFlag && csnFlag) { + return; + } + throw new IllegalArgumentException("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = " + characterEncoding + ", file.encoding=" + csn); + } + public static String getDefaultKeyspace(Properties props) { List keySpaces = Arrays.asList(props.getProperty(Constant.DRIVER_PROPERTY_SCHEMA).split(",")); return keySpaces.get(0); diff --git a/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java b/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java index b94349a..549b9c8 100755 --- a/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java +++ b/src/main/java/com/jd/jdbc/vitess/VitessJdbcUrlParser.java @@ -19,12 +19,7 @@ import com.jd.jdbc.common.Constant; import com.jd.jdbc.sqlparser.utils.StringUtils; import com.jd.jdbc.sqlparser.utils.Utils; -import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.addDefaultProperties; -import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.checkCell; -import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.checkCredentials; import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.checkSchema; -import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.checkServerTimezone; -import static com.jd.jdbc.vitess.VitessJdbcProperyUtil.replaceLegacyPropertyValues; import com.jd.jdbc.vitess.mysql.VitessPropertyKey; import java.net.URI; import java.net.URISyntaxException; @@ -73,11 +68,12 @@ public static Properties parse(String url, Properties info) { } } - checkCell(parsedProperties); - checkCredentials(path, parsedProperties); - checkServerTimezone(parsedProperties); - addDefaultProperties(parsedProperties); - replaceLegacyPropertyValues(parsedProperties); + VitessJdbcProperyUtil.checkCell(parsedProperties); + VitessJdbcProperyUtil.checkCredentials(path, parsedProperties); + VitessJdbcProperyUtil.checkServerTimezone(parsedProperties); + VitessJdbcProperyUtil.addDefaultProperties(parsedProperties); + VitessJdbcProperyUtil.replaceLegacyPropertyValues(parsedProperties); + VitessJdbcProperyUtil.checkCharacterEncoding(parsedProperties); Integer socketTimeout = null; if (parsedProperties.containsKey(VitessPropertyKey.SOCKET_TIMEOUT.getKeyName())) { diff --git a/src/main/java/com/jd/jdbc/vitess/mysql/VitessPropertyKey.java b/src/main/java/com/jd/jdbc/vitess/mysql/VitessPropertyKey.java index 7226916..0bf27df 100644 --- a/src/main/java/com/jd/jdbc/vitess/mysql/VitessPropertyKey.java +++ b/src/main/java/com/jd/jdbc/vitess/mysql/VitessPropertyKey.java @@ -30,7 +30,8 @@ public enum VitessPropertyKey { ALLOW_MULTI_QUERIES("allowMultiQueries"), MAX_ROWS("maxRows"), REWRITE_BATCHED_STATEMENTS("rewriteBatchedStatements"), - ZERO_DATE_TIME_BEHAVIOR("zeroDateTimeBehavior"); + ZERO_DATE_TIME_BEHAVIOR("zeroDateTimeBehavior"), + characterEncoding("characterEncoding"); private final String keyName; diff --git a/src/test/java/com/jd/jdbc/engine/ASCIICharEncodingTest.java b/src/test/java/com/jd/jdbc/engine/ASCIICharEncodingTest.java new file mode 100644 index 0000000..656afb1 --- /dev/null +++ b/src/test/java/com/jd/jdbc/engine/ASCIICharEncodingTest.java @@ -0,0 +1,56 @@ +/* +Copyright 2021 JD Project Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package com.jd.jdbc.engine; + +import java.sql.Connection; +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import testsuite.TestSuite; +import testsuite.internal.TestSuiteShardSpec; +import testsuite.internal.environment.DriverEnv; + +/* +-Dfile.encoding=US-ASCII +Preferences -> Editor -> File Encodings -> Project Encoding + */ +public class ASCIICharEncodingTest extends TestSuite { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Connection conn; + + @Test + public void testAsciiUtf8() throws SQLException { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = UTF-8, file.encoding=US-ASCII"); + init("UTF-8"); + } + + @Test + public void testAsciiGbk() throws SQLException { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = GBK, file.encoding=US-ASCII"); + init("GBK"); + } + + public void init(String charEncoding) throws SQLException { + DriverEnv driverEnv = TestSuite.Driver.of(TestSuiteShardSpec.TWO_SHARDS, charEncoding); + this.conn = getConnection(driverEnv); + } +} diff --git a/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java b/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java index d278a42..6d5d7b3 100644 --- a/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java +++ b/src/test/java/com/jd/jdbc/engine/CharEncodingTest.java @@ -23,17 +23,22 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.Arrays; import org.junit.After; import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import testsuite.TestSuite; import testsuite.internal.TestSuiteShardSpec; import testsuite.internal.environment.DriverEnv; public class CharEncodingTest extends TestSuite { - protected Connection conn; + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Connection conn; @BeforeClass public static void beforeClass() throws NoSuchFieldException, IllegalAccessException { @@ -42,8 +47,6 @@ public static void beforeClass() throws NoSuchFieldException, IllegalAccessExcep public void init(String charEncoding) throws SQLException { DriverEnv driverEnv = TestSuite.Driver.of(TestSuiteShardSpec.TWO_SHARDS, charEncoding); - String url = getConnectionUrl(driverEnv); - System.out.println("Test Url: " + url); this.conn = getConnection(driverEnv); try (Statement stmt = this.conn.createStatement()) { stmt.executeUpdate("delete from plan_test"); @@ -53,12 +56,11 @@ public void init(String charEncoding) throws SQLException { @After public void after() throws IllegalAccessException, NoSuchFieldException, SQLException { InnerConnectionPoolUtil.removeInnerConnectionConfig(conn); - if (conn != null) { - conn.close(); - } + closeConnection(conn); } @Test + @Ignore public void testGBK() throws SQLException { init("GBK"); String insertPstmtSql = "INSERT INTO plan_test (f_tinyint, f_varchar, f_text) VALUES (1, ?, ?);"; @@ -74,19 +76,15 @@ public void testGBK() throws SQLException { while (rs.next()) { int i = rs.getInt(1); String name = rs.getString(2); - System.out.println("Expect:" + "赵欣" + i + "; Actual: " + name); - - System.out.println("(\"赵欣\" + i).getBytes: " + Arrays.toString(("赵欣" + i).getBytes(StandardCharsets.UTF_8))); - System.out.println("rs.getBytes(2)" + Arrays.toString(rs.getBytes(2))); Assert.assertArrayEquals(("赵欣" + i).getBytes(StandardCharsets.UTF_8), rs.getBytes(2)); Assert.assertArrayEquals("小明".getBytes(StandardCharsets.UTF_8), rs.getBytes(3)); - Assert.assertEquals("赵欣" + i, name); } } } @Test + @Ignore public void testDual() throws SQLException { init("GBK"); try (Statement stmt = this.conn.createStatement()) { @@ -107,6 +105,13 @@ public void testDual() throws SQLException { } } + @Test + public void testGBK2() throws SQLException { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Only supports utf8 encoding, please check characterEncoding in jdbcurl and file.encoding in environment variable,characterEncoding = GBK, file.encoding=UTF-8"); + init("GBK"); + } + @Test public void testUTF8() throws SQLException { init("UTF-8"); @@ -123,17 +128,8 @@ public void testUTF8() throws SQLException { while (rs.next()) { int i = rs.getInt(1); String name = rs.getString(2); - System.out.println("Expect:" + "赵欣" + i + "; Actual: " + name); Assert.assertEquals("赵欣" + i, name); } } } - - @After - public void close() throws SQLException { - if (this.conn != null) { - this.conn.close(); - System.out.println("Connection has been closed"); - } - } }