From 6d31ce6bc7c2b29ab91ed348c20b409911149748 Mon Sep 17 00:00:00 2001 From: diego Date: Wed, 21 Dec 2022 14:03:08 +0100 Subject: [PATCH 1/7] bump 3.0.10-SNAPSHOT version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b026aa8dc..a6120e208 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ mariadb-java-client jar mariadb-java-client - 3.0.9 + 3.0.10-SNAPSHOT JDBC driver for MariaDB and MySQL https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/ From 1d9bee54ea2f30edecbf005e018d0f208bd87557 Mon Sep 17 00:00:00 2001 From: diego Date: Wed, 21 Dec 2022 14:04:48 +0100 Subject: [PATCH 2/7] [CONJ-1032] option case-insensitive for compatibility with 2.x --- .../java/org/mariadb/jdbc/Configuration.java | 89 ++++++++++--------- .../jdbc/util/options/OptionAliases.java | 8 +- .../jdbc/unit/util/ConfigurationTest.java | 15 ++++ 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/Configuration.java b/src/main/java/org/mariadb/jdbc/Configuration.java index 6ad1454fa..a22545000 100644 --- a/src/main/java/org/mariadb/jdbc/Configuration.java +++ b/src/main/java/org/mariadb/jdbc/Configuration.java @@ -603,55 +603,64 @@ private static void mapPropertiesToOption(Builder builder, Properties properties // loop on properties, // - check DefaultOption to check that property value correspond to type (and range) // - set values - for (final Object keyObj : properties.keySet()) { - String realKey = OptionAliases.OPTIONS_ALIASES.get(keyObj); - if (realKey == null) realKey = keyObj.toString(); - final Object propertyValue = properties.get(keyObj); - - if (propertyValue != null && realKey != null) { - try { - final Field field = Builder.class.getDeclaredField(realKey); - field.setAccessible(true); - if (field.getGenericType().equals(String.class) - && !propertyValue.toString().isEmpty()) { - field.set(builder, propertyValue); - } else if (field.getGenericType().equals(Boolean.class)) { - switch (propertyValue.toString().toLowerCase()) { - case "": - case "1": - case "true": - field.set(builder, Boolean.TRUE); - break; - - case "0": - case "false": - field.set(builder, Boolean.FALSE); - break; - - default: + Properties remainingProperties = new Properties(); + properties.forEach((key, val) -> remainingProperties.put(key, val)); + + for (Field field : Builder.class.getDeclaredFields()) { + if (remainingProperties.isEmpty()) break; + for (final Object keyObj : remainingProperties.keySet()) { + String realKey = + OptionAliases.OPTIONS_ALIASES.get(keyObj.toString().toLowerCase(Locale.ROOT)); + if (realKey == null) realKey = keyObj.toString(); + final Object propertyValue = remainingProperties.get(keyObj); + + if (propertyValue != null && realKey != null) { + if (realKey.toLowerCase(Locale.ROOT).equals(field.getName().toLowerCase(Locale.ROOT))) { + field.setAccessible(true); + remainingProperties.remove(keyObj); + + if (field.getGenericType().equals(String.class) + && !propertyValue.toString().isEmpty()) { + field.set(builder, propertyValue); + } else if (field.getGenericType().equals(Boolean.class)) { + switch (propertyValue.toString().toLowerCase()) { + case "": + case "1": + case "true": + field.set(builder, Boolean.TRUE); + break; + + case "0": + case "false": + field.set(builder, Boolean.FALSE); + break; + + default: + throw new IllegalArgumentException( + String.format( + "Optional parameter %s must be boolean (true/false or 0/1) was '%s'", + keyObj, propertyValue)); + } + } else if (field.getGenericType().equals(Integer.class)) { + try { + final Integer value = Integer.parseInt(propertyValue.toString()); + field.set(builder, value); + } catch (NumberFormatException n) { throw new IllegalArgumentException( String.format( - "Optional parameter %s must be boolean (true/false or 0/1) was '%s'", + "Optional parameter %s must be Integer, was '%s'", keyObj, propertyValue)); - } - } else if (field.getGenericType().equals(Integer.class)) { - try { - final Integer value = Integer.parseInt(propertyValue.toString()); - field.set(builder, value); - } catch (NumberFormatException n) { - throw new IllegalArgumentException( - String.format( - "Optional parameter %s must be Integer, was '%s'", keyObj, propertyValue)); + } } } - } catch (NoSuchFieldException nfe) { - // keep unknown option: - // those might be used in authentication or identity plugin - nonMappedOptions.put(keyObj, propertyValue); } } } + // keep unknown option: + // those might be used in authentication or identity plugin + remainingProperties.forEach((key, val) -> nonMappedOptions.put(key, val)); + // for compatibility with 2.x if (isSet("useSsl", nonMappedOptions) || isSet("useSSL", nonMappedOptions)) { if (isSet("trustServerCertificate", nonMappedOptions)) { diff --git a/src/main/java/org/mariadb/jdbc/util/options/OptionAliases.java b/src/main/java/org/mariadb/jdbc/util/options/OptionAliases.java index 44c32ecb6..78cc9b156 100644 --- a/src/main/java/org/mariadb/jdbc/util/options/OptionAliases.java +++ b/src/main/java/org/mariadb/jdbc/util/options/OptionAliases.java @@ -15,10 +15,8 @@ public final class OptionAliases { static { OPTIONS_ALIASES = new HashMap<>(); - OPTIONS_ALIASES.put("enabledSSLCipherSuites", "enabledSslCipherSuites"); - OPTIONS_ALIASES.put("serverRSAPublicKeyFile", "serverRsaPublicKeyFile"); - OPTIONS_ALIASES.put("clientCertificateKeyStoreUrl", "keyStore"); - OPTIONS_ALIASES.put("clientCertificateKeyStorePassword", "keyStorePassword"); - OPTIONS_ALIASES.put("clientCertificateKeyStoreType", "keyStoreType"); + OPTIONS_ALIASES.put("clientcertificatekeystoreurl", "keyStore"); + OPTIONS_ALIASES.put("clientcertificatekeystorepassword", "keyStorePassword"); + OPTIONS_ALIASES.put("clientcertificatekeystoretype", "keyStoreType"); } } diff --git a/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java b/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java index 4c929e319..6be58888c 100644 --- a/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java @@ -306,6 +306,21 @@ public void testOptionParse() throws Throwable { assertEquals("toto", conf.password()); } + @Test + public void nonCaseSensitiveOptions() throws Throwable { + Configuration conf = + Configuration.parse( + "jdbc:mariadb://localhost/test?useR=root&paSsword=toto&createdb=true" + + "&autoReConnect=true&prepStMtCacheSize=2&ConnectTimeout=5&socketTimeout=20"); + assertEquals(5, conf.connectTimeout()); + assertEquals(20, conf.socketTimeout()); + assertEquals(2, conf.prepStmtCacheSize()); + assertEquals("true", conf.nonMappedOptions().get("createdb")); + assertEquals("true", conf.nonMappedOptions().get("autoReConnect")); + assertEquals("root", conf.user()); + assertEquals("toto", conf.password()); + } + @Test public void wrongTypeParsing() { Common.assertThrowsContains( From 8d999d84168afcc5f8b80f38dc3ed443ae2c6b30 Mon Sep 17 00:00:00 2001 From: diego Date: Wed, 21 Dec 2022 17:57:15 +0100 Subject: [PATCH 3/7] [CONJ-1023] Connector/J doesn't set SSL cap bit in Handshake Response Packet --- .../java/org/mariadb/jdbc/client/impl/ConnectionHelper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java b/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java index a0bb66177..b65105ef4 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java @@ -242,6 +242,9 @@ public static long initializeClientCapabilities( capabilities |= Capabilities.CONNECT_WITH_DB; } + if (configuration.sslMode() != SslMode.DISABLE) { + capabilities |= Capabilities.SSL; + } return capabilities & serverCapabilities; } From 9f0bec57658acadfb9521637913de131b41829a9 Mon Sep 17 00:00:00 2001 From: diego Date: Fri, 23 Dec 2022 15:18:35 +0100 Subject: [PATCH 4/7] [CONJ-1026] timezone=auto option fails on non-fixed-offset zone machine when server timezone differ from client --- .../jdbc/client/impl/StandardClient.java | 2 +- .../integration/codec/DateTimeCodecTest.java | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java b/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java index 178792d24..9aadabe98 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java @@ -445,7 +445,7 @@ public String createSessionVariableQuery(String serverTz) { sessionCommands.add("time_zone='" + zoneOffset.getId() + "'"); } } else { - sessionCommands.add("time_zone='" + conf.timezone() + "'"); + sessionCommands.add("time_zone='" + clientZoneId.normalized() + "'"); } } } diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java index 116518129..4d444313b 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java @@ -408,6 +408,11 @@ public void getDateTimezoneTest() throws SQLException { try (Connection conGmtm8 = createCon("timezone=auto")) { getDateTimezoneTestGmtm8(conGmtm8, getPrepare(conGmtm8), TimeZone.getTimeZone("GMT-8")); } + TimeZone.setDefault(initialTz); + try (Connection conAuto = createCon("timezone=auto")) { + getDateTimezoneTestNormal(conAuto, getPrepare(conAuto)); + } + } finally { TimeZone.setDefault(initialTz); } @@ -565,6 +570,47 @@ public void getDateTimezoneTestGmtm8(Connection conGmt8, ResultSet rs, TimeZone conGmt8.rollback(); } + public void getDateTimezoneTestNormal(Connection conAuto, ResultSet rs) + throws SQLException { + + assertEquals("2010-01-12 01:55:12.0", rs.getObject(1, Timestamp.class).toString()); + + conAuto.createStatement().execute("TRUNCATE TABLE DateTimeCodec3"); + try (PreparedStatement prep = + conAuto.prepareStatement("INSERT INTO DateTimeCodec3 values (?,?)")) { + prep.setInt(1, 5); + prep.setString(2, "2010-01-12 01:55:12"); + prep.execute(); + + prep.setInt(1, 6); + prep.setObject(2, "2010-01-12 11:55:12"); + prep.execute(); + } + conAuto.commit(); + + java.sql.Statement stmt = conAuto.createStatement(); + stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER + try (PreparedStatement prepStmt = conAuto.prepareStatement("select * from DateTimeCodec3 order by id")) { + rs = prepStmt.executeQuery(); + rs.next(); + assertEquals(5, rs.getInt(1)); + assertEquals("2010-01-12T01:55:12", rs.getObject(2, LocalDateTime.class).toString()); + assertEquals("2010-01-12 01:55:12.000000", rs.getString(2)); + + rs.next(); + + Timestamp tt = Timestamp.valueOf("2010-01-12 01:55:12"); + int offset = TimeZone.getDefault().getOffset(tt.getTime()); + int offsetHour = offset / (3_600_000); + if (offsetHour < 0) offsetHour = offsetHour * -1; + + // test might fail if run in timezone with offset not rounded to hours + assertEquals("2010-01-12T11:55:12" + ((offset < 0) ? "-" : "+") + ((offsetHour < 10) ? "0" : offsetHour / 10) + (offsetHour % 10) + ":00", rs.getObject(2, OffsetDateTime.class).toString()); + assertEquals("2010-01-12 11:55:12.0", rs.getTimestamp(2).toString()); + } + conAuto.rollback(); + } + @Test public void getTime() throws SQLException { getTime(get()); From 609aa2db61501e6d7218c3f6ca4b26d22ad7eb6f Mon Sep 17 00:00:00 2001 From: diego Date: Fri, 23 Dec 2022 15:19:04 +0100 Subject: [PATCH 5/7] [misc] correct Tls test behavior --- src/test/java/org/mariadb/jdbc/integration/SslTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/mariadb/jdbc/integration/SslTest.java b/src/test/java/org/mariadb/jdbc/integration/SslTest.java index d5205d9a1..5d3e89210 100644 --- a/src/test/java/org/mariadb/jdbc/integration/SslTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/SslTest.java @@ -45,7 +45,7 @@ public static void beforeAll2() throws SQLException { Statement stmt = sharedConn.createStatement(); // mysql 8.0.31 broken public key retrieval, so avoid FLUSHING for now - Assumptions.assumeTrue(!isMariaDBServer() && !exactVersion(8, 0, 31)); + Assumptions.assumeTrue(isMariaDBServer() || (!isMariaDBServer() && !exactVersion(8, 0, 31))); stmt.execute("FLUSH PRIVILEGES"); sslPort = System.getenv("TEST_MAXSCALE_TLS_PORT") == null From 794d362fe71722e23d1d7111a4df72a56db4a796 Mon Sep 17 00:00:00 2001 From: diego Date: Mon, 9 Jan 2023 14:44:26 +0100 Subject: [PATCH 6/7] [misc] correct Date test depending on timezone --- .../integration/codec/DateTimeCodecTest.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java index 4d444313b..758afcc18 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java @@ -570,14 +570,13 @@ public void getDateTimezoneTestGmtm8(Connection conGmt8, ResultSet rs, TimeZone conGmt8.rollback(); } - public void getDateTimezoneTestNormal(Connection conAuto, ResultSet rs) - throws SQLException { + public void getDateTimezoneTestNormal(Connection conAuto, ResultSet rs) throws SQLException { assertEquals("2010-01-12 01:55:12.0", rs.getObject(1, Timestamp.class).toString()); conAuto.createStatement().execute("TRUNCATE TABLE DateTimeCodec3"); try (PreparedStatement prep = - conAuto.prepareStatement("INSERT INTO DateTimeCodec3 values (?,?)")) { + conAuto.prepareStatement("INSERT INTO DateTimeCodec3 values (?,?)")) { prep.setInt(1, 5); prep.setString(2, "2010-01-12 01:55:12"); prep.execute(); @@ -590,7 +589,8 @@ public void getDateTimezoneTestNormal(Connection conAuto, ResultSet rs) java.sql.Statement stmt = conAuto.createStatement(); stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER - try (PreparedStatement prepStmt = conAuto.prepareStatement("select * from DateTimeCodec3 order by id")) { + try (PreparedStatement prepStmt = + conAuto.prepareStatement("select * from DateTimeCodec3 order by id")) { rs = prepStmt.executeQuery(); rs.next(); assertEquals(5, rs.getInt(1)); @@ -605,7 +605,17 @@ public void getDateTimezoneTestNormal(Connection conAuto, ResultSet rs) if (offsetHour < 0) offsetHour = offsetHour * -1; // test might fail if run in timezone with offset not rounded to hours - assertEquals("2010-01-12T11:55:12" + ((offset < 0) ? "-" : "+") + ((offsetHour < 10) ? "0" : offsetHour / 10) + (offsetHour % 10) + ":00", rs.getObject(2, OffsetDateTime.class).toString()); + if (offsetHour == 0) { + assertEquals("2010-01-12T11:55:12Z", rs.getObject(2, OffsetDateTime.class).toString()); + } else { + assertEquals( + "2010-01-12T11:55:12" + + ((offset < 0) ? "-" : "+") + + ((offsetHour < 10) ? "0" : offsetHour / 10) + + (offsetHour % 10) + + ":00", + rs.getObject(2, OffsetDateTime.class).toString()); + } assertEquals("2010-01-12 11:55:12.0", rs.getTimestamp(2).toString()); } conAuto.rollback(); From a206124411c391f052a5643ab9120e6be7dc7b5f Mon Sep 17 00:00:00 2001 From: diego Date: Mon, 9 Jan 2023 15:19:04 +0100 Subject: [PATCH 7/7] Bump 3.0.10 --- CHANGELOG.md | 7 +++++++ pom.xml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16668ca64..eb66bbbca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## [3.0.10](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.10) (Jan 2023) +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.9...3.0.10) + +* CONJ-1023 Connector/J doesn't set SSL cap bit in Handshake Response Packet +* CONJ-1026 timezone=auto option failure on non-fixed-offset zone machine +* CONJ-1032 Compatibility for deprecated arguments is case sensitive now + ## [3.0.9](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.9) (Nov 2022) [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.8...3.0.9) * 2.7.7 merge diff --git a/pom.xml b/pom.xml index a6120e208..f70e69b4b 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ mariadb-java-client jar mariadb-java-client - 3.0.10-SNAPSHOT + 3.0.10 JDBC driver for MariaDB and MySQL https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/