From e24a63189499fea924e949dfe400d30b89293976 Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 20 Sep 2023 15:53:45 +0200 Subject: [PATCH 01/26] [misc] use mariadb 11.1 in test suite --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index de8ec181f..e338e00bec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,7 +99,7 @@ jobs: name: "CS 10.11" - env: srv=mariadb v=11.0 local=1 name: "CS 11.0" - - env: srv=mariadb v=11.1-rc local=1 + - env: srv=mariadb v=11.1 local=1 name: "CS 11.1" - env: srv=mariadb v=10.6 packet=40 jdk: openjdk17 From 3710eb0274a6f1f18272d60fe8403e500103e849 Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 20 Sep 2023 15:54:45 +0200 Subject: [PATCH 02/26] [misc] update formatting plugin to com.spotify.fmt/fmt-maven-plugin --- pom.xml | 4 ++-- .../standard/ed25519/spec/EdDSAParameterSpec.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 116cc8b6a..aa96a8e41 100644 --- a/pom.xml +++ b/pom.xml @@ -233,9 +233,9 @@ - com.coveo + com.spotify.fmt fmt-maven-plugin - 2.13 + 2.20 diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java index 30dfe3440..0fa7df90f 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java @@ -60,7 +60,9 @@ public String getHashAlgorithm() { return hashAlgo; } - /** @return the base (generator) */ + /** + * @return the base (generator) + */ public GroupElement getB() { return B; } From e41f024355853da8241ae872ff502007a4790c02 Mon Sep 17 00:00:00 2001 From: rusher Date: Tue, 10 Oct 2023 15:58:14 +0200 Subject: [PATCH 03/26] [misc] correct windows named pipe testing for mysql 8.0.14+ --- .../jdbc/integration/ConnectionTest.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java index f1a4ce8c5..15c253809 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java @@ -935,10 +935,9 @@ public void useNoDatabase() throws SQLException { @Test public void windowsNamedPipe() throws SQLException { - Assumptions.assumeTrue(isMariaDBServer() || !minVersion(8, 0, 14)); ResultSet rs = null; try { - rs = sharedConn.createStatement().executeQuery("select @@named_pipe,@@socket"); + rs = sharedConn.createStatement().executeQuery("select @@named_pipe,@@socket,@@named_pipe_full_access_group"); } catch (SQLException sqle) { // on non Windows system, named_pipe doesn't exist. } @@ -948,10 +947,24 @@ public void windowsNamedPipe() throws SQLException { Assumptions.assumeTrue(rs.getBoolean(1)); String namedPipeName = rs.getString(2); System.out.println("namedPipeName:" + namedPipeName); + if (!isMariaDBServer() && minVersion(8, 0, 14)) { + String namedPipeFullAccess = rs.getString(3); + System.out.println("namedPipeFullAccess:" + namedPipeFullAccess); + Assumptions.assumeTrue(namedPipeFullAccess != null && !namedPipeFullAccess.isEmpty()); + } // skip test if no namedPipeName was obtained because then we do not use a socket connection Assumptions.assumeTrue(namedPipeName != null); - try (Connection connection = createCon("pipe=" + namedPipeName)) { + String connUrl = + password == null || password.isEmpty() + ? String.format( + "jdbc:mariadb:///%s?user=%s%s", database, user, defaultOther) + : String.format( + "jdbc:mariadb:///%s?user=%s&password=%s%s", + database, user, password, defaultOther); + + + try (Connection connection = DriverManager.getConnection(connUrl + "&pipe=" + namedPipeName)) { java.sql.Statement stmt = connection.createStatement(); try (ResultSet rs2 = stmt.executeQuery("SELECT 1")) { assertTrue(rs2.next()); From 65c2f1e8377b4a0c792611d147bd413822afb3aa Mon Sep 17 00:00:00 2001 From: rusher Date: Tue, 10 Oct 2023 16:28:38 +0200 Subject: [PATCH 04/26] [CONJ-1111] ensure using same ip in place of DNS when creating a connection to kill running query --- .../java/org/mariadb/jdbc/Connection.java | 11 ++- .../java/org/mariadb/jdbc/client/Client.java | 7 ++ .../jdbc/client/impl/MultiPrimaryClient.java | 5 ++ .../jdbc/client/impl/StandardClient.java | 6 ++ .../jdbc/integration/ConnectionTest.java | 76 ++++++++++++++++--- .../jdbc/integration/StatementTest.java | 5 +- 6 files changed, 96 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/Connection.java b/src/main/java/org/mariadb/jdbc/Connection.java index 4e9db8b1b..c3fcecdfa 100644 --- a/src/main/java/org/mariadb/jdbc/Connection.java +++ b/src/main/java/org/mariadb/jdbc/Connection.java @@ -94,8 +94,15 @@ public void setPoolConnection(MariaDbPoolConnection poolConnection) { * @throws SQLException never thrown */ public void cancelCurrentQuery() throws SQLException { - try (Client cli = - new StandardClient(conf, client.getHostAddress(), new ReentrantLock(), true)) { + // prefer relying on IP compare to DNS if not using Unix socket/PIPE + String currentIp = client.getSocketIp(); + HostAddress hostAddress = + currentIp == null + ? client.getHostAddress() + : HostAddress.from( + currentIp, client.getHostAddress().port, client.getHostAddress().primary); + + try (Client cli = new StandardClient(conf, hostAddress, new ReentrantLock(), true)) { cli.execute(new QueryPacket("KILL QUERY " + client.getContext().getThreadId()), false); } } diff --git a/src/main/java/org/mariadb/jdbc/client/Client.java b/src/main/java/org/mariadb/jdbc/client/Client.java index 768a8a698..40842322b 100644 --- a/src/main/java/org/mariadb/jdbc/client/Client.java +++ b/src/main/java/org/mariadb/jdbc/client/Client.java @@ -190,4 +190,11 @@ void readStreamingResults( * @return connection host */ HostAddress getHostAddress(); + + /** + * Get current socket IP or null (for Pipe / unix socket) + * + * @return Socket current IP + */ + String getSocketIp(); } diff --git a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java index 6a288ba70..77802c5b9 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java @@ -537,6 +537,11 @@ public HostAddress getHostAddress() { return currentClient.getHostAddress(); } + @Override + public String getSocketIp() { + return currentClient.getSocketIp(); + } + public boolean isPrimary() { return true; } 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 2b50e1ebd..6bc993304 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java @@ -1023,6 +1023,12 @@ public void close() { } } + public String getSocketIp() { + return this.socket.getInetAddress() == null + ? null + : this.socket.getInetAddress().getHostAddress(); + } + public boolean isPrimary() { return hostAddress.primary; } diff --git a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java index 15c253809..7e0a8d8cd 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java @@ -14,6 +14,8 @@ import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.junit.jupiter.api.*; import org.mariadb.jdbc.*; import org.mariadb.jdbc.integration.util.SocketFactoryBasicTest; @@ -937,7 +939,10 @@ public void useNoDatabase() throws SQLException { public void windowsNamedPipe() throws SQLException { ResultSet rs = null; try { - rs = sharedConn.createStatement().executeQuery("select @@named_pipe,@@socket,@@named_pipe_full_access_group"); + rs = + sharedConn + .createStatement() + .executeQuery("select @@named_pipe,@@socket,@@named_pipe_full_access_group"); } catch (SQLException sqle) { // on non Windows system, named_pipe doesn't exist. } @@ -956,15 +961,14 @@ public void windowsNamedPipe() throws SQLException { // skip test if no namedPipeName was obtained because then we do not use a socket connection Assumptions.assumeTrue(namedPipeName != null); String connUrl = - password == null || password.isEmpty() - ? String.format( - "jdbc:mariadb:///%s?user=%s%s", database, user, defaultOther) - : String.format( - "jdbc:mariadb:///%s?user=%s&password=%s%s", - database, user, password, defaultOther); + password == null || password.isEmpty() + ? String.format("jdbc:mariadb:///%s?user=%s%s", database, user, defaultOther) + : String.format( + "jdbc:mariadb:///%s?user=%s&password=%s%s", + database, user, password, defaultOther); - - try (Connection connection = DriverManager.getConnection(connUrl + "&pipe=" + namedPipeName)) { + try (Connection connection = + DriverManager.getConnection(connUrl + "&pipe=" + namedPipeName)) { java.sql.Statement stmt = connection.createStatement(); try (ResultSet rs2 = stmt.executeQuery("SELECT 1")) { assertTrue(rs2.next()); @@ -987,6 +991,60 @@ public void windowsNamedPipe() throws SQLException { } } + @Test + public void windowsNamedPipeCancel() throws SQLException { + Assumptions.assumeFalse(isMariaDBServer()); + ResultSet rs = null; + try { + rs = + sharedConn + .createStatement() + .executeQuery("select @@named_pipe,@@socket,@@named_pipe_full_access_group"); + } catch (SQLException sqle) { + // on non Windows system, named_pipe doesn't exist. + } + if (rs != null) { + assertTrue(rs.next()); + System.out.println("named_pipe:" + rs.getString(1)); + Assumptions.assumeTrue(rs.getBoolean(1)); + String namedPipeName = rs.getString(2); + System.out.println("namedPipeName:" + namedPipeName); + if (!isMariaDBServer() && minVersion(8, 0, 14)) { + String namedPipeFullAccess = rs.getString(3); + System.out.println("namedPipeFullAccess:" + namedPipeFullAccess); + Assumptions.assumeTrue(namedPipeFullAccess != null && !namedPipeFullAccess.isEmpty()); + } + + // skip test if no namedPipeName was obtained because then we do not use a socket connection + Assumptions.assumeTrue(namedPipeName != null); + String connUrl = + password == null || password.isEmpty() + ? String.format("jdbc:mariadb:///%s?user=%s%s", database, user, defaultOther) + : String.format( + "jdbc:mariadb:///%s?user=%s&password=%s%s", + database, user, password, defaultOther); + + try (Connection connection = + DriverManager.getConnection(connUrl + "&pipe=" + namedPipeName)) { + Statement stmt = connection.createStatement(); + stmt.cancel(); // will do nothing + + ExecutorService exec = Executors.newFixedThreadPool(1); + + Common.assertThrowsContains( + SQLTimeoutException.class, + () -> { + exec.execute(new StatementTest.CancelThread(stmt)); + stmt.execute( + "select * from information_schema.columns as c1, information_schema.tables, information_schema" + + ".tables as t2"); + exec.shutdown(); + }, + "Query execution was interrupted"); + } + } + } + @Test public void localSocket() throws Exception { Assumptions.assumeTrue( diff --git a/src/test/java/org/mariadb/jdbc/integration/StatementTest.java b/src/test/java/org/mariadb/jdbc/integration/StatementTest.java index a090d1dee..51ca05503 100644 --- a/src/test/java/org/mariadb/jdbc/integration/StatementTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/StatementTest.java @@ -619,8 +619,7 @@ public void testWarnings() throws SQLException { @Test public void cancel() throws Exception { Assumptions.assumeTrue( - isMariaDBServer() - && !"maxscale".equals(System.getenv("srv")) + !"maxscale".equals(System.getenv("srv")) && !"skysql".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv")) && !isXpand()); @@ -937,7 +936,7 @@ public void closeOnCompletion() throws SQLException { assertTrue(stmt.isClosed()); } - private static class CancelThread implements Runnable { + static class CancelThread implements Runnable { private final java.sql.Statement stmt; From 23d6e4142d7e45950860e82f4e953969129ef1a6 Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 16 Oct 2023 17:32:39 +0200 Subject: [PATCH 05/26] [CONJ-1112] code style validation change library com.spotify.fmt:fmt-maven-plugin is not compatible with java 21, replaced by com.theoryinpractise:googleformatter-maven-plugin --- CHANGELOG.md | 656 ++++++++++------ CONTRIBUTING.md | 65 +- README.md | 18 +- pom.xml | 20 +- src/benchmark/README.md | 11 +- .../java/org/mariadb/jdbc/Common.java | 3 +- src/benchmark/java/org/mariadb/jdbc/Do_1.java | 11 +- .../java/org/mariadb/jdbc/Do_1000_params.java | 4 +- .../java/org/mariadb/jdbc/Insert_batch.java | 5 +- .../java/org/mariadb/jdbc/Select_1.java | 3 +- .../org/mariadb/jdbc/Select_1000_Rows.java | 3 +- .../org/mariadb/jdbc/Select_100_cols.java | 6 +- src/benchmark/resources/logback-test.xml | 20 +- .../mariadb/jdbc/BaseCallableStatement.java | 6 +- .../mariadb/jdbc/BasePreparedStatement.java | 18 +- .../java/org/mariadb/jdbc/Configuration.java | 729 +++++++++--------- .../java/org/mariadb/jdbc/Connection.java | 106 +-- src/main/java/org/mariadb/jdbc/Driver.java | 10 +- .../java/org/mariadb/jdbc/HostAddress.java | 15 +- .../org/mariadb/jdbc/MariaDbDataSource.java | 20 +- .../mariadb/jdbc/MariaDbPoolConnection.java | 30 +- .../mariadb/jdbc/MariaDbPoolDataSource.java | 20 +- src/main/java/org/mariadb/jdbc/Statement.java | 32 +- .../mariadb/jdbc/TransactionIsolation.java | 36 +- .../mariadb/jdbc/client/ColumnDecoder.java | 249 +++--- .../java/org/mariadb/jdbc/client/Context.java | 28 +- .../org/mariadb/jdbc/client/DataType.java | 8 +- .../mariadb/jdbc/client/ReadableByteBuf.java | 19 +- .../jdbc/client/context/BaseContext.java | 30 +- .../jdbc/client/impl/MultiPrimaryClient.java | 10 +- .../jdbc/client/impl/PrepareCache.java | 2 + .../jdbc/client/impl/StandardClient.java | 22 +- .../client/impl/StandardReadableByteBuf.java | 7 +- .../mariadb/jdbc/client/result/Result.java | 49 +- .../client/result/rowdecoder/RowDecoder.java | 9 + .../jdbc/client/socket/impl/PacketReader.java | 5 +- .../jdbc/client/socket/impl/PacketWriter.java | 27 +- .../client/socket/impl/UnixDomainSocket.java | 13 +- .../mariadb/jdbc/client/util/MutableInt.java | 4 +- .../mariadb/jdbc/export/ExceptionFactory.java | 1 + .../java/org/mariadb/jdbc/export/HaMode.java | 12 +- .../export/MaxAllowedPacketException.java | 1 + .../mariadb/jdbc/message/ClientMessage.java | 80 +- .../message/client/BulkExecutePacket.java | 7 +- .../jdbc/message/client/ExecutePacket.java | 9 +- .../message/client/PrepareExecutePacket.java | 8 +- .../jdbc/message/server/AuthSwitchPacket.java | 26 +- .../server/ColumnDefinitionPacket.java | 26 +- .../message/server/PrepareResultPacket.java | 12 +- .../standard/CachingSha2PasswordPlugin.java | 154 ++-- .../standard/ed25519/math/Field.java | 2 + .../standard/ed25519/math/GroupElement.java | 428 +++++----- .../math/ed25519/Ed25519FieldElement.java | 4 +- .../ed25519/Ed25519LittleEndianEncoding.java | 44 +- .../ed25519/spec/EdDSANamedCurveTable.java | 10 +- .../jdbc/plugin/codec/BigDecimalCodec.java | 30 +- .../mariadb/jdbc/plugin/codec/TimeCodec.java | 1 + .../tls/main/DefaultTlsSocketPlugin.java | 38 +- .../jdbc/util/constants/ServerStatus.java | 12 + .../jdbc/util/constants/StateChange.java | 5 + .../org/mariadb/jdbc/util/log/Loggers.java | 66 +- .../org/mariadb/jdbc/client/SocketHelper.java | 5 +- .../mariadb/jdbc/integration/BatchTest.java | 46 +- .../org/mariadb/jdbc/integration/Common.java | 76 +- .../jdbc/integration/ConnectionTest.java | 290 +++---- .../jdbc/integration/LocalInfileTest.java | 64 +- .../jdbc/integration/PoolDataSourceTest.java | 46 +- .../integration/PreparedStatementTest.java | 22 +- .../org/mariadb/jdbc/integration/SslTest.java | 64 +- .../jdbc/integration/StatementTest.java | 42 +- .../jdbc/integration/codec/BlobCodecTest.java | 2 +- .../codec/MultiPolygonCodecTest.java | 58 +- .../jdbc/unit/util/log/JdkLoggerTest.java | 96 +-- src/test/resources/logback-test.xml | 26 +- 74 files changed, 2205 insertions(+), 1937 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4938f7618..b8b60450a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,45 +1,56 @@ # Change Log - ## [3.2.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.2.0) (Aug 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.4...3.2.0) ##### Notable Changes -* CONJ-920 Java batched statements with optimistic locking failing. the option `useBulkStmts` is now disable by default, a new option `useBulkStmtsForInserts` is enable by default, permetting using bulk for INSERT commands only. This permits optimistic behavior working by default. -* CONJ-1084 When using maxscale 23.08.0+, and a maxscale node fails, connector will now priorize reconnection to the maxscale node having less connection, to ensure repartition after failover -* CONJ-1088 Implement `databaseTerm` option for mysql compatibility + +* CONJ-920 Java batched statements with optimistic locking failing. the option `useBulkStmts` is now disable by default, + a new option `useBulkStmtsForInserts` is enabled by default, permitting using bulk for INSERT commands only. This + permits optimistic behavior working by default. +* CONJ-1084 When using maxscale 23.08.0+, and a maxscale node fails, connector will now priorize reconnection to the + maxscale node having less connection, to ensure repartition after failover +* CONJ-1088 Implement `databaseTerm` option for mysql compatibility * CONJ-1096 adding option `useLocalSessionState` to permit avoiding queries when application only use JDBC methods. ##### Bugs Fixed + * CONJ-1075 LOAD DATA INFILE is broken on windows -* CONJ-1079 getGeneratedKeys after batch will not return all generated id's if first batch command return no generated id. -* CONJ-1080 maridb Java connector sslMode=verify-ca complaining unable to find trust certificate. +* CONJ-1079 getGeneratedKeys after batch will not return all generated id's if first batch command return no generated + id. +* CONJ-1080 mariadb Java connector sslMode=verify-ca complaining unable to find trust certificate. * CONJ-1082 Multiple session system variables parsing fails -* CONJ-1083 Using /*client prepare*/ prefix to force client side prepared statement -* CONJ-1091 can't make a connection when the Read Replica DB is in a hang state when SocketTimeout=0 set +* CONJ-1083 Using /*client prepare*/ prefix to force client side prepared statement +* CONJ-1091 can't make a connection when the Read Replica DB is in a hang state when SocketTimeout=0 set * CONJ-1092 ensure respecting server collation -* CONJ-1094 Missing mariadb/mysql collation - +* CONJ-1094 Missing mariadb/mysql collation ## [3.0.11](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.11) (Aug 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.10...3.0.11) -* CONJ-1089 correcting 3.0.10 incompatibility with in java 8 +* CONJ-1089 correcting 3.0.10 incompatibility with in java 8 ## [2.7.10](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.10) (Aug 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.9...2.7.10) -* CONJ-1091 Ensure setting connectTimeout as timeout for socket timeout until connection is done. This permit to set a connectTimeout, while socketTimeout can still be set to 0 +* CONJ-1091 Ensure setting connectTimeout as timeout for socket timeout until connection is done. This permit to set a + connectTimeout, while socketTimeout can still be set to 0 ## [3.1.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.4) (Apr 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.3...3.1.4) * CONJ-1065 wrong Resultset.wasNull() for zero-date timestamps -* CONJ-1070 getBlob on TEXT columns throw Exception -* CONJ-1071 Error response during Bulk execution might result in connection wrong state -* CONJ-1067 When some numeric data types are set to UNSIGNED, ResultSetMetaData.getColumnTypeName() does not return UNSIGNED +* CONJ-1070 getBlob on TEXT columns throw Exception +* CONJ-1071 Error response during Bulk execution might result in connection wrong state +* CONJ-1067 When some numeric data types are set to UNSIGNED, ResultSetMetaData.getColumnTypeName() does not return + UNSIGNED ## [3.1.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.3) (Mar 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.2...3.1.3) * CONJ-1054 Threadsafety issue when using CredentialPlugin in v3.x @@ -50,65 +61,74 @@ * report 2.7.9 bug fixes CONJ-1062 and CONJ-1063 ## [2.7.9](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.9) (Mar 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.8...2.7.9) * CONJ-1062 correcting TlsSocketPlugin to use Driver classloader * CONJ-1063 DatabaseMetaData.getTypeInfo() returns wrong value for UNSIGNED_ATTRIBUTE ## [3.1.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.2) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.1...3.1.2) * CONJ-1040 possible ConcurrentModificationException when connecting * CONJ-1041 possible ArrayIndexOutOfBoundsException ## [2.7.8](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.8) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.7...2.7.8) * CONJ-1039 setQueryTimeout not honored by CallableStatement for procedures depending on security context * CONJ-1041 possible ArrayIndexOutOfBoundsException * CONJ-1023 set missing SSL capability in handshake after SSL exchanges - ## [3.1.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.1) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.0...3.1.1) - 3.0.10 bug fix: - - 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 -- CONJ-1036 org.mariadb.jdbc.client.socket.impl.PacketWriter.writeAscii() broken in 3.1.0 - + - 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 +- CONJ-1036 org.mariadb.jdbc.client.socket.impl.PacketWriter.writeAscii() broken in 3.1.0 ## [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 +* 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.1.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.0) (Nov 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.9...3.1.0) ##### Notable Changes + * CONJ-899 Support UUID Object * CONJ-916 when a failover occurs, log replayed transaction * CONJ-917 deprecated options use must be logged * CONJ-992 load balance distribution -* CONJ-1008 default value for socket option useReadAheadInput -* CONJ-1009 improve performance reading big result-set -* CONJ-1014 avoid creating array when receiving server packet -* CONJ-1015 pipelining sending multiple packet to socket +* CONJ-1008 default value for socket option useReadAheadInput +* CONJ-1009 improve performance reading big result-set +* CONJ-1014 avoid creating array when receiving server packet +* CONJ-1015 pipelining sending multiple packet to socket ##### Bugs Fixed -* CONJ-1020 java 11 option setting ignored + +* CONJ-1020 java 11 option setting ignored ## [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 -* CONJ-1012 stored procedure register output parameter as null if set before registerOutParameter command +* CONJ-1012 stored procedure register output parameter as null if set before registerOutParameter command * CONJ-1017 Calendar possible race condition, cause wrong timestamp setting ## [2.7.7](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.7) (Nov 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.6...2.7.7) * CONJ-1021 GSSAPI authentication might result in connection reset @@ -118,13 +138,16 @@ * CONJ-1007 Socket file descriptors are leaked after connecting with unix socket if DB is not up running ## [3.0.8](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.8) (Sept 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.7...3.0.8) ##### Notable Changes + * small performance improvement * [CONJ-1010] improve client side prepared parameter parameter substitution - + ##### Bugs Fixed + * [CONJ-997] regression in 3.x when using option galeraAllowedState resulting in an IndexOutOfBoundsException * [CONJ-1002] 2nd failover reconnection ignores default database/schema setting when not set by connection string * [CONJ-1003] replication configuration always use 1st replica on 3.0 @@ -134,19 +157,20 @@ * [CONJ-1010] improve client side prepare statement parameter substitution * [CONJ-999] setting createDatabaseIfNotExist option use on read-only server will refuse connection on 3.0 - ## [3.0.7](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.7) (Jul 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.6...3.0.7) -* [CONJ-993] SQLDataException reading DATA_TYPE on DatabaseMetaData.getTypeInfo() after 3.0.4 -* [CONJ-986] Permit specific Statement.setLocalInfileInputStream for compatibility -* [CONJ-987] Version 3.0.0 returns String for VARBINARY instead of byte[] as 2.7.6 did +* [CONJ-993] SQLDataException reading DATA_TYPE on DatabaseMetaData.getTypeInfo() after 3.0.4 +* [CONJ-986] Permit specific Statement.setLocalInfileInputStream for compatibility +* [CONJ-987] Version 3.0.0 returns String for VARBINARY instead of byte[] as 2.7.6 did * [CONJ-989] Binary column read as String -* [CONJ-990] Setting timezone=UTC result in SQLSyntaxErrorException -* [CONJ-991] Regression: binary(16) is returned as String by getObject() +* [CONJ-990] Setting timezone=UTC result in SQLSyntaxErrorException +* [CONJ-991] Regression: binary(16) is returned as String by getObject() * [CONJ-994] Version 3.x rejects previously accepted boolean string parameter for BOOLEAN field ## [3.0.6](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.6) (Jun 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.5...3.0.6) * [CONJ-953] PreparedStatement.getGeneratedKeys() returns rows when no keys are generated in insert @@ -158,30 +182,32 @@ * [CONJ-985] ResultSet.getObject() returns ByteSet instead of Byte[] for BIT ## [3.0.5](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.5) (may 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.4...3.0.5) -* [CONJ-956] ArrayIndexOutOfBoundsException when alias length > 250 -* [CONJ-947] value after milliseconds precision lost when timestamp is encoded +* [CONJ-956] ArrayIndexOutOfBoundsException when alias length > 250 +* [CONJ-947] value after milliseconds precision lost when timestamp is encoded * [CONJ-949] keep clientCertificateKeyStoreUrl and clientCertificateKeyStoreUrl aliases * [CONJ-950] metadata TEXT/TINYTEXT/MEDIUMTEXT/LONGTEXT wrong column type and length * [CONJ-954] java.time.OffsetDateTime not supported -* [CONJ-958] compatibility with 2.7: now loop through hosts when multiple host without failover mode -* [CONJ-959] java.time.Instant not supported -* [CONJ-961] LOAD DATA LOCAL INFILE was disable by default -* [CONJ-962] resultset for negative TIME value return erronous LocalDateTime values +* [CONJ-958] compatibility with 2.7: now loop through hosts when multiple host without failover mode +* [CONJ-959] java.time.Instant not supported +* [CONJ-961] LOAD DATA LOCAL INFILE was disable by default +* [CONJ-962] resultset for negative TIME value return erronous LocalDateTime values * [CONJ-965] better error message when not loading serverSslCert file -* [CONJ-967] clearParameters() breaks validity when using output parameters in stored procedures +* [CONJ-967] clearParameters() breaks validity when using output parameters in stored procedures * [CONJ-969] org.mariadb.jdbc.ClientPreparedStatement is missing a toString implementation, useful for logging - ## [3.0.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.4) (Mar 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.3...3.0.4) * [CONJ-915] javadoc addition * [CONJ-921] DatabaseMetadata#getTables with null value for tableNamePattern throws Syntax error * [CONJ-922] DECIMAL overflow for long/int/short not throwing exception * [CONJ-924] NULL column type might result in java.lang.IllegalArgumentException: Unexpected datatype NULL -* [CONJ-926] Client restrict authentication to 'mysql_native_password,client_ed25519,auth_gssapi_client' if restrictedAuth parameter is not set +* [CONJ-926] Client restrict authentication to 'mysql_native_password,client_ed25519,auth_gssapi_client' if + restrictedAuth parameter is not set * [CONJ-924] NULL column test correction * [CONJ-923] correctly return 64 bits generated id / updated rows * [CONJ-933] load-balancing failover doesn't timeout @@ -194,17 +220,19 @@ * [CONJ-940] Permit updating rows when not having primary info on metadata (Xpand) * [CONJ-939] add Xpand testing - ## [3.0.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.3) (Jan 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.2-rc...3.0.3) -* [CONJ-908] correct Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) to return generated keys +* [CONJ-908] correct Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) to return + generated keys * [CONJ-909] adding createDatabaseIfNotExist option for 2.x compatibility * [CONJ-910] permit jdbc:mysql scheme when connection string contains "permitMysqlScheme" for compatibility * [CONJ-913] Avoid executing additional command on connection for faster connection creation * [CONJ-912] remove security manager code (JEP 411) * [CONJ-911] enable keep-alive by default -* failover improvement. some specific commands not in transaction are considered to be replayed in case of failover, like PING, PREPARE, ROLLBACK, ... +* failover improvement. some specific commands not in transaction are considered to be replayed in case of failover, + like PING, PREPARE, ROLLBACK, ... * CONJ-705 parameter metadata get parameter count even when query cannot be prepared * prepareStatement.addBatch must initialize with previous set * Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) must return generated keys @@ -218,57 +246,63 @@ * [CONJ-901] ArrayIndexOutOfBoundsException on StandardReadableByteBuf.readByte error ## [3.0.2-rc](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.2-rc) (31 Aug 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.1-beta...3.0.2-rc) * CONJ-879 Java 9 module full support - * Aws IAM credential now use sdk v2 authentication that support java 9 modularity + * Aws IAM credential now use sdk v2 authentication that support java 9 modularity * CONJ-896 Ensure pool connections validation when a socket fail * CONJ-897 Ensure having connection's thread id in Exception / debug logs -minor: -* Ensure travis testing for PR/fork +minor: + +* Ensure travis testing for PR/fork ## [3.0.1-beta](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.1-beta) (29 Jul 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.0-alpha...3.0.1-beta) * CONJ-879 Provide JPMS module descriptor * CONJ-880 metadata query performance correction * CONJ-884 MariaDbPoolDataSource leaks connections when the mariadb server restarts * CONJ-885 org.mariadb.jdbc.internal.util.pool.Pool swallows SQLException during addConnection -* CONJ-891 getImportedKeys with null catalog restrict result to current database +* CONJ-891 getImportedKeys with null catalog restrict result to current database * CONJ-894 Adding useMysqlMetadata for 2.7 compatibility - ## [2.7.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.4) (29 Jul 2021) -[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.3...2.7.4) -* CONJ-890 getImportedKeys/getTables regression returning an empty resultset for null/empty catalog -* CONJ-863 Ensure socket state when SocketTimeout occurs -* CONJ-873 IndexOutOfBoundsException when executing prepared queries using automatic key generation in parallel -* CONJ-884 MariaDbPoolDataSource leaks connections when the mariadb server restarts -* CONJ-893 DatabaseMetaData.getColumns regression causing TINYINT(x) with x > 1 to return BIT type in place of TINYINT -* CONJ-889 CallableStatement using function throw wrong error on getter +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.3...2.7.4) +* CONJ-890 getImportedKeys/getTables regression returning an empty resultset for null/empty catalog +* CONJ-863 Ensure socket state when SocketTimeout occurs +* CONJ-873 IndexOutOfBoundsException when executing prepared queries using automatic key generation in parallel +* CONJ-884 MariaDbPoolDataSource leaks connections when the mariadb server restarts +* CONJ-893 DatabaseMetaData.getColumns regression causing TINYINT(x) with x > 1 to return BIT type in place of TINYINT +* CONJ-889 CallableStatement using function throw wrong error on getter ## [3.0.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.0) (3 May 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.2...3.0.0) -This version is a total rewrite of java driver. +This version is a total rewrite of java driver. * complete rewrite, code clarification, reduced size (15%), more than 90% coverage tested. * Encoding/decoding implementation are now registred by Codec, permitting codec registry implementation - * example support of Geometry Object + * example support of Geometry Object * Permit authentication plugin restriction by option `restrictedAuth` * performance improvement: * Prepare and execution are now using pipelining when using option `useServerPrepStmts` - * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata (see https://jira.mariadb.org/browse/MDEV-19237) + * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata ( + see https://jira.mariadb.org/browse/MDEV-19237) +correction: -correction: -* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock exception +* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock + exception * CONJ-858 Properties parameter that differ from string not taken in account ### Easy logging + If using slf4J, just enabled package "org.mariadb.jdbc" log. level ERROR will log connection error @@ -276,19 +310,21 @@ level WARNING will log query errors level DEBUG will log queries level TRACE will log all exchanges with server. -If not using slf4J, console will be used. -If really wanting to use JDK logger, System property "mariadb.logging.fallback" set to JDK will indicate to use common logging. - +If not using slf4J, console will be used. +If really wanting to use JDK logger, System property "mariadb.logging.fallback" set to JDK will indicate to use common +logging. ### Failover -Failover implementation now permit redoing transaction : -when creating a transaction, all command will be cached, and can be replayed in case of failover. + +Failover implementation now permit redoing transaction : +when creating a transaction, all command will be cached, and can be replayed in case of failover. This functionality can be enabled using option `transactionReplay`. -This is not enabled by default, because this required that application to avoid using non-idempotent commands. +This is not enabled by default, because this required that application to avoid using non-idempotent commands. example: + ```sql START TRANSACTION; select next_val(hibernate_sequence); @@ -301,37 +337,40 @@ COMMIT; ### Allow setup of TCP_KEEPIDLE, TCP_KEEPCOUNT, TCP_KEEPINTERVAL Equivalent options are `tcpKeepIdle`, `tcpKeepCount`, `tcpKeepInterval` -Since available only with java 11, setting this option with java < 11 will have no effect. +Since available only with java 11, setting this option with java < 11 will have no effect. ## [2.7.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.3) (12 May 2021) -[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.2...2.7.3) -* CONJ-619 Multiple batch update fails after LOAD DATA LOCAL INFILE -* CONJ-854 LOAD XML INFILE breaks when using LOCAL -* CONJ-855 throwing more specific exception for updatable result-set that can not be updated by ResultSet -* CONJ-857 Remove use of mysql.proc table, relying on information_schema.parameters -* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock exception -* CONJ-866 long binary parsing improvement -* CONJ-871 OSGi: Missing Import-Package in Connector/J bundle (javax.sql.rowset.serial) -* CONJ-878 option serverSslCert file location -* CONJ-880 metadata query performance correction -* CONJ-858 Properties.put with object that differ from String supported even if use is not recommended -* CONJ-861 executeBatch must not clear last parameter value. -* CONJ-883 using unix socket, hostname is not mandatory anymore +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.2...2.7.3) +* CONJ-619 Multiple batch update fails after LOAD DATA LOCAL INFILE +* CONJ-854 LOAD XML INFILE breaks when using LOCAL +* CONJ-855 throwing more specific exception for updatable result-set that can not be updated by ResultSet +* CONJ-857 Remove use of mysql.proc table, relying on information_schema.parameters +* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock + exception +* CONJ-866 long binary parsing improvement +* CONJ-871 OSGi: Missing Import-Package in Connector/J bundle (javax.sql.rowset.serial) +* CONJ-878 option serverSslCert file location +* CONJ-880 metadata query performance correction +* CONJ-858 Properties.put with object that differ from String supported even if use is not recommended +* CONJ-861 executeBatch must not clear last parameter value. +* CONJ-883 using unix socket, hostname is not mandatory anymore ## [2.7.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.2) (29 Jan. 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.1...2.7.2) * CONJ-847 NPE at UpdatableResultSet#close -* CONJ-849 driver now doesn't close connection caused java.io.NotSerializableException as a result of incorrect data bind to a prepared statement parameter +* CONJ-849 driver now doesn't close connection caused java.io.NotSerializableException as a result of incorrect data + bind to a prepared statement parameter * CONJ-850 MariaDbResultSetMetaData#getPrecision(int) now returns correct length for character data * CONJ-851 metadata getBestRowIdentifier incompatibility with MySQL 8 correction * CONJ-853 Support Aurora cluster custom endpoints * CONJ-852 ON DUPLICATE KEY detection failed when using new line - ## [2.7.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.1) (23 Nov. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.0...2.7.1) * CONJ-834 use of BULK batch is conditioned by capability, not checking server version @@ -340,39 +379,42 @@ Since available only with java 11, setting this option with java < 11 will have * CONJ-841 ResultSetMetaData::getColumnTypeName() returns incorrect type name for LONGTEXT * CONJ-842 Byte array parameters are now send as long data * CONJ-837 prepared statement cache leak on ResultSet CONCUR_UPDATABLE concurrency -* CONJ-843 ParameterMetaData::getParameterType for CallableStatement parameter return expected "BINARY" value for BINARY type +* CONJ-843 ParameterMetaData::getParameterType for CallableStatement parameter return expected "BINARY" value for BINARY + type minor: + * CONJ-845 test suite now test SkySQL with replication setting * CONJ-838 have a 'replica' alias for 'slave' connection option - ## [2.7.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.0) (24 Sep. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.6.2...2.7.0) -* CONJ-805 maxFieldSize string truncation occurs on bytes' length, not character length -* CONJ-807 Correcting possible Get Access Denied error if using multiple classloader -* CONJ-810 normalization of resultset getDate/getTime of timestamp field. -* CONJ-812 DatabaseMetadata.getBestRowIdentifier and getMaxProcedureNameLength correction -* CONJ-813 setConfiguration not being called on classes that extend ConfigurableSocketFactory -* CONJ-816 Table with primary key with DEFAULT function can be inserted for 10.5 servers -* CONJ-817 Switched position of REMARKS and PROCEDURE_TYPE in the getProcedures result -* CONJ-820 MySQLPreparedStatement.setObject can now handle java.lang.Character type -* CONJ-828 new option `ensureSocketState` to ensure protocol state -* CONJ-829 Option to cache callablestatement is now disabled by default -* CONJ-830 connector now throw a better error if SSL is mandatory and server doesn't support SSL -* CONJ-814 Small possible improvement of getCrossReference, getExportedKeys and getImportedKey -* CONJ-825 XAResource.isSameRM implementation +* CONJ-805 maxFieldSize string truncation occurs on bytes' length, not character length +* CONJ-807 Correcting possible Get Access Denied error if using multiple classloader +* CONJ-810 normalization of resultset getDate/getTime of timestamp field. +* CONJ-812 DatabaseMetadata.getBestRowIdentifier and getMaxProcedureNameLength correction +* CONJ-813 setConfiguration not being called on classes that extend ConfigurableSocketFactory +* CONJ-816 Table with primary key with DEFAULT function can be inserted for 10.5 servers +* CONJ-817 Switched position of REMARKS and PROCEDURE_TYPE in the getProcedures result +* CONJ-820 MySQLPreparedStatement.setObject can now handle java.lang.Character type +* CONJ-828 new option `ensureSocketState` to ensure protocol state +* CONJ-829 Option to cache callablestatement is now disabled by default +* CONJ-830 connector now throw a better error if SSL is mandatory and server doesn't support SSL +* CONJ-814 Small possible improvement of getCrossReference, getExportedKeys and getImportedKey +* CONJ-825 XAResource.isSameRM implementation ## [2.6.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.6.2) (23 Jul. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.6.1...2.6.2) * CONJ-804 - Automatic charset correction * CONJ-809 - SelectResultSet's (ResultSet)MetaData always indicates all columns to be readonly * CONJ-802 - Version parsing depending on Classloader might result in connection Exception - ## [2.6.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.6.1) (23 Jun. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.6.0...2.6.1) * CONJ-781 - DatabaseMetaData.supportsMultipleResultSets() now return correctly true. @@ -381,7 +423,8 @@ minor: * CONJ-775 - avoid a NPE for malformed "jdbc:mariadb:///" connection string. * CONJ-776 - Temporal Data Tables are not listed in metadata * CONJ-785 - corrected escape sequence for multiple backslash escape -* CONJ-786 - Connection.setReadOnly(true ) with option `assureReadOnly` now force read only connection even for mono server* +* CONJ-786 - Connection.setReadOnly(true ) with option `assureReadOnly` now force read only connection even for mono + server* * CONJ-795 - permit resultset.getRow() for TYPE_FORWARD_ONLY when streaming * CONJ-797 - Connector set UTF8mb4 equivalent in case of server configured with UTF8mb3 collation * CONJ-800 - implement Statement setEscapeProcessing to avoid escape @@ -394,9 +437,11 @@ minor: * CONJ-782 - SkySQL testing ## [2.6.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.6.0) (19 Mar. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.4...2.6.0) -* CONJ-768 - Check Galera allowed state when connecting when option `galeraAllowedState` is set, and not only on validation +* CONJ-768 - Check Galera allowed state when connecting when option `galeraAllowedState` is set, and not only on + validation * CONJ-759 - on failover, catalog changed might not be set when automatically recreating a connection. * CONJ-761 - remove unnecessary dependencies for fedora tar creation * CONJ-763 - Custom SocketFactory now can change options @@ -408,12 +453,14 @@ minor: * CONJ-772 - JDBC Conversion Function support parsing correction ## [2.5.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.4) (27 Jan. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.3...2.5.4) * CONJ-756 - Logging correction when using enablePacketDebug option * CONJ-755 - permits avoiding setting session_track_schema with new option `trackSchema` ## [2.5.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.3) (07 Jan. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.2...2.5.3) * CONJ-752 - Manifest file wrong entry - thanks to Christoph Läubrich @@ -421,14 +468,15 @@ minor: * CONJ-747 - JDBC Conversion Function fast-path skipped, always using longer implementation ## [2.5.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.2) (22 Nov. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.1...2.5.2) * CONJ-745 - use pool reset only for corrected COM_RESET_CONNECTION * CONJ-743 - byte signed value wrong serialization for text protocol * CONJ-742 - ensure plugin using Driver classloader - ## [2.5.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.1) (15 Oct. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.0...2.5.1) * CONJ-736 - OSGI compliance @@ -436,28 +484,33 @@ minor: * CONJ-738 - PAM authentication multiple exchanges permitting multiple step in connection string * CONJ-735 - Multi insert regression correction returning multi generated keys - ## [2.5.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.0) (02 Oct. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.4...2.5.0) -* CONJ-663 - Client authentication plugins are now defined as services. The driver has 2 new plugins `caching_sha2_password` and `sha256_password plugin` for MySQL compatibility +* CONJ-663 - Client authentication plugins are now defined as services. The driver has 2 new + plugins `caching_sha2_password` and `sha256_password plugin` for MySQL compatibility * CONJ-733 - Credential service: AWS IAM authentication * CONJ-727 - Support configuration of custom SSLSocketFactory -* CONJ-561 - JDBC 4.3 partial implementation java.sql.Statement methods isSimpleIdentifier, enquoteIdentifier, enquoteLiteral and enquoteNCharLiteral +* CONJ-561 - JDBC 4.3 partial implementation java.sql.Statement methods isSimpleIdentifier, enquoteIdentifier, + enquoteLiteral and enquoteNCharLiteral * CONJ-692 - ConnectionPoolDataSource interface addition to MariaDbPoolDataSource * CONJ-563 - closing possible option batch thread on driver registration. * CONJ-732 - Driver getPropertyInfo returns no options' information when url is empty * CONJ-734 - DatabaseMetaData.getSchemaTerm now return "schema", not empty string ## [2.4.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.4) (14 Sep. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.3...2.4.4) * CONJ-724 - Do not ignore the Calendar parameter in ResultSet#getTime(int, Calendar) * CONJ-725 - Connection Failure when using PAM authenticated user on 10.4 MariaDB server -* CONJ-729 - master-slave regression: commit on read-only server Executed only when there is an active transaction on master connection +* CONJ-729 - master-slave regression: commit on read-only server Executed only when there is an active transaction on + master connection * CONJ-726 - removing possible NPE after failover on aurora cluster ## [2.4.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.3) (02 Jul. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.2...2.4.3) * CONJ-717 - conversion function support for other data type than default MariaDB conversion type @@ -466,39 +519,50 @@ minor: * CONJ-716 - Correcting possible NPE on non thread safe NumberFormat (logging) ## [2.4.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.2) (17 Jun. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.1...2.4.2) Security + * CONJ-679 - parse Query when receiving LOAD LOCAL INFILE Bugs + * CONJ-703 - ClassNotFoundException when trying to connect using two-authentication in an OSGI environment. * CONJ-711 - Xid format id is unsigned integer, currently sending as signed value. * CONJ-700 - autoReconnect=true on Basic Failover doesn't reconnect -* CONJ-707 - failover might throw an unexpected exception with using "failover"/"sequential" configuration on socket error -* CONJ-709 - includeThreadDumpInDeadlockExceptions is thrown only if option includeInnodbStatusInDeadlockExceptions is set +* CONJ-707 - failover might throw an unexpected exception with using "failover"/"sequential" configuration on socket + error +* CONJ-709 - includeThreadDumpInDeadlockExceptions is thrown only if option includeInnodbStatusInDeadlockExceptions is + set * CONJ-710 - Throw complete stackTrace when having an exception on XA Commands * CONJ-714 - Error on connection on galera server when in detached mode. * CONJ-701 - typo in error message in SelectResultSet.java ## [2.4.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.1) (15 Mar. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.0...2.4.1) Evolutions + * misc - enabled running of 'SHOW ENGINE INNODB STATUS' for error code 1213 (@mtykhenko) * misc - reduce mutex using select @@innodb_read_only for aurora (@matsuzayaws) Bugs + * misc - updating checkstyle version dependency * misc - permit using SSL on localsocket * CONJ-687 - addition of option "useMysqlMetadata" to permit MySQL meta compatibility * misc - java PID using java 9 ProcessHandle if existing, relying on JNA if present -* CONJ-682 - internal pool correction: when receiving an RST during connection validation, the pool will end up throwing connection timeout exception in place of reusing another connection. +* CONJ-682 - internal pool correction: when receiving an RST during connection validation, the pool will end up throwing + connection timeout exception in place of reusing another connection. ## [2.4.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.0) (28 Jan. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.3.0...2.4.0) Evolutions + * CONJ-675 - permit multiple alternative authentication methods for the same user (future MariaDB 10.4 feature) * CONJ-678 - permit indication of truststore/keystore type (JKS/PKCS12), then not relying on java default type * CONJ-378 - GSSAPI: client can provide SPN @@ -509,14 +573,15 @@ Evolutions New options -|Option|Description| -|---|---| -|useReadAheadInput|use a buffered inputSteam that read socket available data.
Default: true| -|keyStoreType|indicate key store type (JKS/PKCS12). default is null, then using java default type.| -|trustStoreType|indicate trust store type (JKS/PKCS12). default is null, then using java default type| -|servicePrincipalName|when using GSSAPI authentication, SPN (Service Principal Name) use the server SPN information. When set, connector will use this value, ignoring server information| +| Option | Description | +|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| useReadAheadInput | use a buffered inputSteam that read socket available data.
Default: true | +| keyStoreType | indicate key store type (JKS/PKCS12). default is null, then using java default type. | +| trustStoreType | indicate trust store type (JKS/PKCS12). default is null, then using java default type | +| servicePrincipalName | when using GSSAPI authentication, SPN (Service Principal Name) use the server SPN information. When set, connector will use this value, ignoring server information | Bugs + * CONJ-646 - possible NullPointerException when connection lost to database using aurora configuration with one node * CONJ-672 - batch using multi-send can hang when using query timeout * CONJ-544 - disable SSL session resumption when using SSL @@ -530,12 +595,13 @@ Bugs * CONJ-674 - make dumpQueriesOnException = false by default as per documentation minor: + * CONJ-644 - small optimization when validating galera connection * CONJ-625 - add coverage test * CONJ-654 - DatabaseMetaData.getDriverName() returns connector/J with a lowercase c - ## [2.3.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.3.0) (06 Sep. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.6...2.3.0) #### [CONJ-398] Improve deadlock debugging capabilities @@ -543,82 +609,99 @@ minor: MariaDB has now 2 new options to permit identifying deadlock : New options -|Option|Description| -|---|---| -|includeInnodbStatusInDeadlockExceptions|add "SHOW ENGINE INNODB STATUS" result to exception trace when having a deadlock exception.
//Default: false| -|includeThreadDumpInDeadlockExceptions|add thread dump to exception trace when having a deadlock exception.
Default: false| +| Option | Description | +|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| includeInnodbStatusInDeadlockExceptions | add "SHOW ENGINE INNODB STATUS" result to exception trace when having a deadlock exception.
//Default: false | +| includeThreadDumpInDeadlockExceptions | add thread dump to exception trace when having a deadlock exception.
Default: false | #### [CONJ-639] the option "enabledSslProtocolSuites" now include TLSv1.2 by default -previous default value was "TLSv1, TLSv1.1", disabling TLSv1.2 by default, due to a corrected issue (MDEV-12190) with servers using YaSSL - not openSSL. Server error was . -Now, the default value is "TLSv1, TLSv1.1, TLSv1.2". So TLSv1.2 can be use directly. -Connecting MySQL community server use YaSSL without correction, and connection might result in SSLException: "Unsupported record version Unknown-0.0". +previous default value was "TLSv1, TLSv1.1", disabling TLSv1.2 by default, due to a corrected issue (MDEV-12190) with +servers using YaSSL - not openSSL. Server error was . +Now, the default value is "TLSv1, TLSv1.1, TLSv1.2". So TLSv1.2 can be use directly. +Connecting MySQL community server use YaSSL without correction, and connection might result in SSLException: " +Unsupported record version Unknown-0.0". #### [CONJ-642] disable the option "useBulkStmts" by default + Using useBulkStmts permit faster batch, but cause one major issue : Batch return -1 = SUCCESS_NO_INFO Different option use this information for optimistic update, and cannot confirm if update succeed or not. This option still makes sense, since for big batch is way faster, but will not be activated by default. - ##= Minor change: + * CONJ-628 - optimization to read metadata faster -* CONJ-637 - java.sql.Driver class implement DriverPropertyInfo[] getPropertyInfo, permitting listing options on querying tools +* CONJ-637 - java.sql.Driver class implement DriverPropertyInfo[] getPropertyInfo, permitting listing options on + querying tools * CONJ-639 - enabledSslProtocolSuites does not include TLSv1.2 by default * CONJ-641 - update maven test dependencies for java 10 compatibility -* CONJ-643 - PreparedStatement::getParameterMetaData always returns VARSTRING as type resulting in downstream libraries interpreting values wrongly +* CONJ-643 - PreparedStatement::getParameterMetaData always returns VARSTRING as type resulting in downstream libraries + interpreting values wrongly ##= Bug correction: -* CONJ-616 - correction on possible NPE on getConnection when using failover configuration and master is down, not throwing a proper exception -* CONJ-636 - Error in batch might throw a NPE and not the proper Exception +* CONJ-616 - correction on possible NPE on getConnection when using failover configuration and master is down, not + throwing a proper exception +* CONJ-636 - Error in batch might throw a NPE and not the proper Exception ## [2.2.6](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.6) (19 Jul. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.5...2.2.6) minor change: + * CONJ-623 - Increase connection logging when Primary node connection fails * CONJ-384 - Permit knowing affected rows number, not only real changed rows New options |=useAffectedRows|default correspond to the JDBC standard, reporting real affected rows. if -enable, will report "affected" rows. example : if enabled, an update command that doesn't change a row value will still be "affected", then report.
Default: false. Since 2.2.6 +enable, will report "affected" rows. example : if enabled, an update command that doesn't change a row value will still +be "affected", then report.
Default: false. Since 2.2.6 Bug correction: + * CONJ-624 - MariaDbPoolDataSource possible NPE on configuration getter * CONJ-623 - Increase connection logging when Primary node connection fails * CONJ-622 - The option "connectTimeout" must take in account DriverManager.getLoginTimeout() when set * CONJ-621 - wrong escaping when having curly bracket in table/field name * CONJ-618 - Client preparestatement parsing error on escaped ' / " in query - ## [2.2.5](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.5) (28 May. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.4...2.2.5) minor change: + * CONJ-602 - Add server hostname to connection packet for proxy * CONJ-604 - handle support for mysql 8.0 tx_isolation replacement by transaction_isolation Bug correction: + * CONJ-613 - Connection using "replication" Parameters fail when no slave is available * CONJ-595 - Create option to configure DONOR/DESYNCED Galera nodes to be unavailable for load-balancing * CONJ-605 - Newlines where breaking calling stored procedures -* CONJ-609 - Using getDate with function DATE_ADD() with parameter using string format where return wrong result using binary protocol +* CONJ-609 - Using getDate with function DATE_ADD() with parameter using string format where return wrong result using + binary protocol * CONJ-610 - Option "allowMasterDownConnection" improvement on connection validation and Exceptions on master down ## [2.2.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.4) (04 May. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.3...2.2.4) Minor changes: + * CONJ-580 - Some options are missing in documentation like default 'autocommit' value * CONJ-597 - Internal exchanges send utf8mb4 with server even if default server collation is not utf8/utf8mb4 * CONJ-600 - Upgrading non-mandatory Waffle dependency to 1.9.0 (windows GSSAPI authentication) * CONJ-575 - test addition to ensure YaSSL downgrade TLSv1.2 protocol to TLSv1.1 ## [2.2.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.3) (08 Mar. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.2...2.2.3) Bug correction: + * CONJ-583 - possible hang indefinitely using master/slave configuration and failover occur * CONJ-586 - erroneous transaction state when first command result as error * CONJ-587 - using allowMasterDownConnection option can lead to NPE when using setReadOnly() @@ -626,9 +709,11 @@ Bug correction: * CONJ-534 - Connection.isValid() must be routed to Master and Slave connections to avoid any server timeout ## [2.2.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.2) (20 Feb. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.1...2.2.2) Bug correction: + * CONJ-564 - Never ever throw an instance of java.lang.Error * CONJ-579 - Keywords missing from DatabaseMetaData.getSQLKeywords() * CONJ-567 - UrlParser.initialUrl gets overwritten @@ -639,81 +724,90 @@ Bug correction: * CONJ-570 - Add tests for 10.3.3 INVISIBLE column ## [2.2.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.1) (22 Dec. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.0...2.2.1) * CONJ-501 - provide support for authentication plugin ed25519 Bug correction: -* CONJ-529 - failover : the driver will pause for 250ms if no servers are available before attempting to reconnect another time + +* CONJ-529 - failover : the driver will pause for 250ms if no servers are available before attempting to reconnect + another time * CONJ-548 - don't use COM_STMT_BULK_EXECUTE for INSERT ... SELECT statements -* CONJ-549 - correction on connection reset when using MariaDbPoolDataSource with options useServerPrepStmts and useResetConnection enabled +* CONJ-549 - correction on connection reset when using MariaDbPoolDataSource with options useServerPrepStmts and + useResetConnection enabled * CONJ-555 - failover caused by client timeout must not reuse connection * CONJ-558 - removing extra ".0" to resultset.getString() value for FLOAT/DOUBLE fields * CONJ-550 - fetching state correction when reusing statement without having read all results * CONJ-553 - RejectedExecutionException was thrown when having large amount of concurrent batches - - ## [2.2.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.0) (08 Nov. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.1.2...2.2.0) Evolutions: + #### CONJ-522 - Pool datasource implementation MariaDB has now 2 different Datasource implementation : + * MariaDbDataSource : Basic implementation. A new connection each time method getConnection() is called. -* MariaDbPoolDataSource : Connection pooling implementation. MariaDB Driver will keep a pool of connection and borrow Connections when asked for it. +* MariaDbPoolDataSource : Connection pooling implementation. MariaDB Driver will keep a pool of connection and borrow + Connections when asked for it. New options -|Option|Description| -|---|---| -|pool|Use pool. This option is useful only if not using a DataSource object, but only connection object.
Default: false. since 2.2.0| -|poolName|Pool name that will permit to identify thread.
default: auto-generated as MariaDb-pool- since 2.2.0| -|maxPoolSize| The maximum number of physical connections that the pool should contain.
Default: 8. since 2.2.0| -|minPoolSize| When connection are removed since not used since more than "maxIdleTime", connections are closed and removed from pool. "minPoolSize" indicate the number of physical connections the pool should keep available at all times. Should be less or equal to maxPoolSize.
Default: maxPoolSize value. Since 2.2.0| -|poolValidMinDelay| When asking a connection to pool, Pool will validate connection state. "poolValidMinDelay" permit to disable this validation if connection has been borrowed recently avoiding useless verification in case of frequent reuse of connection. 0 meaning validation is done each time connection is asked.
Default: 1000 (in milliseconds). Since 2.2.0| -|maxIdleTime|The maximum amount of time in seconds that a connection can stay in pool when not used. This value must always be below @wait_timeout value - 45s
Default: 600 in seconds (=10 minutes), minimum value is 60 seconds. Since 2.2.0| -|staticGlobal|Indicate the following global variable (@@max_allowed_packet,@@wait_timeout,@@autocommit,@@auto_increment_increment,@@time_zone,@@system_time_zone,@@tx_isolation) values won't changed, permitting to pool to create new connection faster.
Default: false. Since 2.2.0| -|useResetConnection|When a connection is closed() (give back to pool), pool reset connection state. Setting this option, session variables change will be reset, and user variables will be destroyed when server permit it (MariaDB >= 10.2.4, MySQL >= 5.7.3), permitting to save memory on server if application make extensive use of variables
Default: false. Since 2.2.0| +| Option | Description | +|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| pool | Use pool. This option is useful only if not using a DataSource object, but only connection object.
Default: false. since 2.2.0 | +| poolName | Pool name that will permit to identify thread.
default: auto-generated as MariaDb-pool- since 2.2.0 | +| maxPoolSize | The maximum number of physical connections that the pool should contain.
Default: 8. since 2.2.0 | +| minPoolSize | When connection are removed since not used since more than "maxIdleTime", connections are closed and removed from pool. "minPoolSize" indicate the number of physical connections the pool should keep available at all times. Should be less or equal to maxPoolSize.
Default: maxPoolSize value. Since 2.2.0 | +| poolValidMinDelay | When asking a connection to pool, Pool will validate connection state. "poolValidMinDelay" permit to disable this validation if connection has been borrowed recently avoiding useless verification in case of frequent reuse of connection. 0 meaning validation is done each time connection is asked.
Default: 1000 (in milliseconds). Since 2.2.0 | +| maxIdleTime | The maximum amount of time in seconds that a connection can stay in pool when not used. This value must always be below @wait_timeout value - 45s
Default: 600 in seconds (=10 minutes), minimum value is 60 seconds. Since 2.2.0 | +| staticGlobal | Indicate the following global variable (@@max_allowed_packet,@@wait_timeout,@@autocommit,@@auto_increment_increment,@@time_zone,@@system_time_zone,@@tx_isolation) values won't changed, permitting to pool to create new connection faster.
Default: false. Since 2.2.0 | +| useResetConnection | When a connection is closed() (give back to pool), pool reset connection state. Setting this option, session variables change will be reset, and user variables will be destroyed when server permit it (MariaDB >= 10.2.4, MySQL >= 5.7.3), permitting to save memory on server if application make extensive use of variables
Default: false. Since 2.2.0 | Other evolutions: + * CONJ-530 - Permit Connection.abort() forcing killing the connection, even if connection is stuck in another thread * CONJ-531 - permit cancelling streaming result-set using Statement.cancel. * CONJ-495 - Improve reading result-set data * CONJ-510 - allow execution of read-only statements on slaves when master is down - Bug : + * CONJ-532 - correction Statement.getMoreResults() for multi-queries -* CONJ-533 - PrepareStatement.setTime() may insert incorrect time according to current timezone, time and option "useLegacyDatetimeCode" +* CONJ-533 - PrepareStatement.setTime() may insert incorrect time according to current timezone, time and option " + useLegacyDatetimeCode" * CONJ-535 - correction on numerical getter for big BIT data type fields * CONJ-541 - Fix behavior of ResultSet#relative when crossing result set boundaries - Misc: + * CONJ-469 - Improve Blob/Clob implementation (avoiding array copy from result-set row) * CONJ-539 - better message when server close connection * misc - resultset.findColumn method use column name if alias not found * misc - default option "connectTimeout" value to 30 seconds (was 0 = no timeout) * misc - ensure that enablePacketDebug option works when timer tick is big - - ## [2.1.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.1.2) (24 Sep. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.1.1...2.1.2) Bug : + * CONJ-525 - Batch result-set return array correction when DELETE statement when bulk option is used * CONJ-526 - better error message getting metadata information when SQL syntax is wrong * CONJ-527 - Resultset.last() return wrong value if resultset has only one result * CONJ-528 - Error executing LOAD DATA LOCAL INFILE when file is larger than max_allowed_packet - ## [2.1.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.1.1) (05 Sep. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.1.0...2.1.1) Bug : + * CONJ-519 - Updatable result-set possible NPE when same field is repeated. * CONJ-514 - ResultSet method wasNull() always return true after a call on a "null-date" field binary protocol handling * CONJ-516 - Permit using updatable result-set when fetching @@ -721,19 +815,23 @@ Bug : * CONJ-515 - Improve MariaDB driver stability in case JNA errors misc : + * correct typo in error message when setting wrong parameter * add trace to HostnameVerifier implementation * handling connection error when no database is provided - ## [2.1.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.1.0) (29 Jul. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.3...2.1.0) ##= CONJ-422 : verification of SSL Certificate Name Mismatch -When using ssl, driver check hostname against the server's identity as presented in the server's Certificate (checking alternative names or certificate CN) to prevent man-in-the-middle attack. +When using ssl, driver check hostname against the server's identity as presented in the server's Certificate (checking +alternative names or certificate CN) to prevent man-in-the-middle attack. A new option "disableSslHostnameVerification" permit to deactivate this validation. -|=disableSslHostnameVerification| When using ssl, driver check hostname against the server's identity as presented in the server's Certificate (checking alternative names or certificate CN) to prevent man-in-the-middle attack. This option permit to deactivate this validation.
//Default: false. Since 2.1.0// +|=disableSslHostnameVerification| When using ssl, driver check hostname against the server's identity as presented in +the server's Certificate (checking alternative names or certificate CN) to prevent man-in-the-middle attack. This option +permit to deactivate this validation.
//Default: false. Since 2.1.0// ##= CONJ-400 - Galera validation When configuration with multi-master, Connection.isValid() will not only validate connection, but primary state. @@ -758,40 +856,45 @@ rs.updateRow(); } }}} - ##= CONJ-389 - faster batch insert -Use dedicated [COM_STMT_BULK_EXECUTE |https://mariadb.com/kb/en/mariadb/com_stmt_bulk_execute/] protocol for batch insert when possible. +Use dedicated [COM_STMT_BULK_EXECUTE |https://mariadb.com/kb/en/mariadb/com_stmt_bulk_execute/] protocol for batch +insert when possible. (batch without Statement.RETURN_GENERATED_KEYS and streams) to have faster batch. (significant only if server MariaDB ≥ 10.2.7) A new option "useBulkStmts" permit to deactivate this functionality. -|=useBulkStmts| Use dedicated COM_STMT_BULK_EXECUTE protocol for batch insert when possible. (batch without Statement.RETURN_GENERATED_KEYS and streams) to have faster batch. (significant only if server MariaDB ≥ 10.2.7)
//Default: true. Since 2.1.0// - +|=useBulkStmts| Use dedicated COM_STMT_BULK_EXECUTE protocol for batch insert when possible. (batch without +Statement.RETURN_GENERATED_KEYS and streams) to have faster batch. (significant only if server MariaDB ≥ +10.2.7)
//Default: true. Since 2.1.0// other evolution + * CONJ-508 - Connection.getCatalog() optimisation for 10.2+ server using new session_track_schema capabilities * CONJ-492 - Failover handle automatic reconnection on KILL command Bug + * CONJ-502 - isolation leak when using multiple pools on same VM on failover * CONJ-503 - regression on aurora Connection.isReadOnly() * CONJ-505 - correcting issue that ended throwing "Unknown prepared statement handler given to mysqld_stmt_execute" * CONJ-496 - return rounded numeric when querying on a decimal field in place of throwing an exception for compatibility - ## [2.0.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.3) (27 Jun. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.2...2.0.3) Bug + * CONJ-473 - when useServerPrepStmts is not set, the PREPARE statement must not be cached. * CONJ-494 - Handle PrepareStatement.getParameterMetaData() if query cannot be PREPAREd * CONJ-497 - escape string correction for big query - ## [2.0.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.2) (05 Jun. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.1...2.0.2) Bug + * CONJ-490 - DataSource connectTimeout is in second, but was set on socket timeout that is in milliseconds * CONJ-481 - Buffer overrun reading ResultSet when using option "useServerPrepStmts" * CONJ-470 - Error when executing SQL contains "values" and rewriteBatchedStatements=true @@ -804,11 +907,13 @@ Bug * CONJ-489 - javax.transaction.xa.XAException message error truncated ( near '0x ) Task + * CONJ-478 - Change CI tests to use maxscale 2.1 version * CONJ-482 - Connection.setNetworkTimeout don't throw exception if no executor * CONJ-488 - Use java.net.URL to read keyStore and trustStore again ## [2.0.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.1) (10 May. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.0-RC...2.0.1) * CONJ-467 - changing database metadata to 4.2 @@ -819,11 +924,12 @@ Task * CONJ-465 - new option "enablePacketDebug" New Options : -|=enablePacketDebug|Driver will save the last 16 MySQL packet exchanges (limited to first 1000 bytes).
Hexadecimal value of this packet will be added to stacktrace when an IOException occur.
This options has no performance incidence (< 1 microseconds per query) but driver will then take 16kb more memory.//Default: true. Since 1.6.0//| +|=enablePacketDebug|Driver will save the last 16 MySQL packet exchanges (limited to first 1000 bytes).
Hexadecimal +value of this packet will be added to stacktrace when an IOException occur.
This options has no performance +incidence (< 1 microseconds per query) but driver will then take 16kb more memory.//Default: true. Since 1.6.0//| * CONJ-468 - autoIncrementIncrement value loaded during connection, avoiding a query for first statement for rewrite - ## [2.0.0-RC](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.0-RC) (20 Apr. 2017) Release candidate version. @@ -835,30 +941,36 @@ Implement some protocol changes that permit to save some bytes.(part of https:// ##= CONJ-341 : handle SERVER_SESSION_STATE_CHANGE status flag With server with version MariaDB 10.2, MySQL 5.7, ensure driver state : -- driver does now always get current database, even database is changed by query. -- when using rewriteBatchedStatements does return correct autoincrement ids even when session variable @auto_increment_increment has change during session. +- driver does now always get current database, even database is changed by query. +- when using rewriteBatchedStatements does return correct autoincrement ids even when session variable + @auto_increment_increment has change during session. ##= CONJ-393 : improve setQueryTimeout to use SET STATEMENT max_statement_time -Previous implementation of query timeout handling (using Statement.setQueryTimeout) will create an additional thread with a scheduler. -When timeout is reached, a temporary connection will be created to permit executing "KILL QUERY ", then closing the temporary connection. +Previous implementation of query timeout handling (using Statement.setQueryTimeout) will create an additional thread +with a scheduler. +When timeout is reached, a temporary connection will be created to permit executing "KILL +QUERY ", then closing the temporary connection. When query ended before timeout, the scheduled task will be canceled. If server is > 10.1.2, query timeout will be handle server side using "SET MAX_STATEMENT_TIME FOR" command. ##= [CONJ-315] -Closing a Statement that was fetching a result-set (using Statement.setFetchSize) and all rows where not read at the time of closing, a kill query command +Closing a Statement that was fetching a result-set (using Statement.setFetchSize) and all rows where not read at the +time of closing, a kill query command will be executed on close, to avoid having to parse all remaining results. ##= [CONJ-442] Memory optimization : streaming query. -Very big command now doesn't use any intermediate buffer. Commands are sent directly to socket avoiding using memory, This permit to send very large object (1G) without using any additional memory. +Very big command now doesn't use any intermediate buffer. Commands are sent directly to socket avoiding using memory, +This permit to send very large object (1G) without using any additional memory. ##= [CONJ-366] Faster connection : bundle first commands in authentication packet -Driver execute different command on connection. Those queries are now send using pipeline (all queries are sent, then only all results are reads). +Driver execute different command on connection. Those queries are now send using pipeline (all queries are sent, then +only all results are reads). New Options : |=usePipelineAuth|Fast connection creation.//Default: true. Since 2.0.0//| @@ -867,6 +979,7 @@ New Options : Parsing row result optimisation to avoid creating byte array to the maximum for faster results and less memory use. ##= Remaining JDBC 4.2 missing implementation : + - CONJ-414 - support for large update count [CONJ-414] - CONJ-409 - PrepareStatement.setObject(...) support for with java 8 temporal object. - CONJ-411 - support for Statement maxFieldSize @@ -887,8 +1000,8 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-411 - Implement Statement maxFieldSize * CONJ-449 - Permit CallableStatement streaming - ## 1.5.9 + * CONJ-212 : Implement password encoding charset option * CONJ-423 : Permit to have MySQL driver and MariaDB driver in same classpath * CONJ-431 : multi-values queries return only one generated key @@ -898,9 +1011,11 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-446 : ResultSet first() throw an exception for scroll type if TYPE_FORWARD_ONLY when streaming * CONJ-440 : handle very big COM_STMT_SEND_LONG_DATA packet (1Gb) * CONJ-429 : ResultSet.getDouble/getFloat may throw a NumberFormatException -* CONJ-438 : using option rewriteBatchedStatements, permit rewrite when query has column/table that contain 'select' keyword. +* CONJ-438 : using option rewriteBatchedStatements, permit rewrite when query has column/table that contain 'select' + keyword. ## 1.5.8 + * CONJ-424 : getGeneratedKeys() on table without generated key failed on second execution * CONJ-412 : Metadata take in account tinyInt1isBit in method columnTypeClause * CONJ-418 : ResultSet.last() isLast() afterLast() and isAfterLast() correction when streaming @@ -911,12 +1026,13 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-420 : High CPU usage against Aurora after 2 hours inactivity ## 1.5.7 + * CONJ-407 : handling failover when packet > max_allowed_packet reset the connection state. * CONJ-403 : possible NPE on ResultSet.close() correction * CONJ-405 : Calendar instance not cleared before being used in ResultSet.getTimestamp - ## 1.5.6 + * CONJ-399 : resultSet getLong() for BIGINT column fails if value is Long.MIN_VALUE in Text protocol * CONJ-395 : Aurora does not randomise selection of read replicas * CONJ-392 : Aurora cluster endpoint detection timezone issue @@ -927,6 +1043,7 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-396 : handling multiple resultSet correctly (was failing if more than 2) ## 1.5.5 + * CONJ-386 : Disabling useBatchMultiSend option for Aurora, since can hang connection. * CONJ-385 : Store procedure with resultSet get wrong getUpdateCount() value (0 in place of -1) * CONJ-383 : permit OldAuthSwitchRequest protocol (compatibility with 5.5 server using plugin) @@ -940,12 +1057,15 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-362 : fix a possible race condition MariaDbPooledConnection ## 1.5.4 + * CONJ-363 : Connection.getClientInfo implementation correction to follow JDBC rules * CONJ-361 : PrepareStatement setString() with empty string correction. -* CONJ-360 : replacing ManagementFactory.getRuntimeMXBean() that cause possible slow connection depending on JVM / environment +* CONJ-360 : replacing ManagementFactory.getRuntimeMXBean() that cause possible slow connection depending on JVM / + environment * CONJ-359 : Metadata getColumns(...) resultSet doesnt have "IS_GENERATEDCOLUMN" info ## 1.5.3 + * CONJ-358 : Permit using private key with password that differ from keyStore password * CONJ-356 : secure connection : use KeyStore private key and associate public keys certificates only * CONJ-342 : Empty clientCertificateKeyStoreUrl option correction @@ -956,32 +1076,43 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-350 : make prepare fallback to client prepare if query cannot be prepared ## 1.5.2 + Release version + * CONJ-331 : clearWarnings() now throw exception on closed connection * CONJ-299 : PreparedStatement.setObject(Type.BIT, "1") registered as true. * CONJ-293 : permit named pipe connection without host * CONJ-333 : ResultSet.getString() of PreparedStatement return NULL When TIME column value=00:00:00 RC corrections + * CONJ-335 : Pool connection may fail to connect with good user * CONJ-332 : option enabledSslCipherSuites rely on java supportedCipherSuites (replacing enabledCipherSuites) * UTF-8 conversion correction ## 1.5.1 + Release candidate version + ### Evolution + #### Aurora host auto-discovery + (CONJ-325) Aurora now auto discover nodes from cluster endpoint. ##### Aurora endpoints -Every aurora instance has a specific endpoint, i.e. a URL that identify the host. Those endpoints look like `xxx.yyy.zzz.rds.amazonaws.com`. +Every aurora instance has a specific endpoint, i.e. a URL that identify the host. Those endpoints look +like `xxx.yyy.zzz.rds.amazonaws.com`. -There is another endpoint named "cluster endpoint" (format `xxx.cluster-yyy.zzz.rds.amazonaws.com`) which is assigned to the current master instance and will change when a new master is promoted. +There is another endpoint named "cluster endpoint" (format `xxx.cluster-yyy.zzz.rds.amazonaws.com`) which is assigned to +the current master instance and will change when a new master is promoted. -In previous version, cluster endpoint use was discouraged, since when a failover occur, this cluster endpoint can point for a limited time to a host that isn't the current master anymore. Old recommandation was to list all specific end-points, like :
+In previous version, cluster endpoint use was discouraged, since when a failover occur, this cluster endpoint can point +for a limited time to a host that isn't the current master anymore. Old recommandation was to list all specific +end-points, like :
{{{ jdbc:mariadb:aurora://a.yyy.zzz.rds.amazonaws.com.com,b.yyy.zzz.rds.amazonaws.com.com/db }}} @@ -990,35 +1121,47 @@ This kind of url string will still work, but now, recommended url string has to jdbc:mariadb:aurora://xxx.cluster-yyy.zzz.rds.amazonaws.com/db }}} -Driver will automatically discover master and slaves of this cluster from current cluster end-point during connection time. This permit to add new replicas to the cluster instance will be discovered without changing driver configuration. +Driver will automatically discover master and slaves of this cluster from current cluster end-point during connection +time. This permit to add new replicas to the cluster instance will be discovered without changing driver configuration. -This discovery append at connection time, so if you are using pool framework, check if this framework as a property that controls the maximum lifetime of a connection in the pool, and set a value to avoid infinite lifetime. When this lifetime is reached, pool will discard the current connection, and create a new one (if needed). New connections will use the new replicas. +This discovery append at connection time, so if you are using pool framework, check if this framework as a property that +controls the maximum lifetime of a connection in the pool, and set a value to avoid infinite lifetime. When this +lifetime is reached, pool will discard the current connection, and create a new one (if needed). New connections will +use the new replicas. (If connections are never discarded, new replicas will begin be used only when a failover occur) - ### Bugfix + * CONJ-329 and CONJ-330 : rewriteBatchedStatements execute single query exceptions correction.

## 1.5.0 + Release candidate version + ### Use native SSPI windows implementation + CONJ-295.
Java kerberos implementation is not well implemented with windows : -* need a Windows registry entry (HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTGTSessionKey) so windows shared current ticket to java. + +* need a Windows registry entry ( + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTGTSessionKey) so windows shared + current ticket to java. * java kinit must be executed to create a Ticket. * restriction when client with local admin rights * ... [see openJDK issue](https://bugs.openjdk.java.net/browse/JDK-6722928) for more information -Kerberos GSSAPI implementation on Windows in now based on [Waffle](https://github.com/dblock/waffle) that support windows SSPI based on [JNA](https://github.com/java-native-access/jna).
+Kerberos GSSAPI implementation on Windows in now based on [Waffle](https://github.com/dblock/waffle) that support +windows SSPI based on [JNA](https://github.com/java-native-access/jna).
if waffle-jna (and dependencies) is on classpath, native implementation will automatically be used. This removes all those problems ### Support for TLSv1.1 and TLSv1.2 + CONJ-249/CONJ-301
Driver before version 1.5 support only TLSv1.
@@ -1026,24 +1169,34 @@ Default supported protocol are now TLSv1 and TLSv1.1, other protocols can be act MariaDB and MySQL community server permit TLSv1 and TLSv1.1.
MariaDB server from version 10.0.15 is using the openSSL library permitting TLSv1.2 (>= 5.5.41 for the 5.5 branch). -//YaSSL doesn't support TLSv1.2, so if MariaDB server is build from sources with YaSSL, only TLSv1 and TLSv1.1 will be available, even for version > 10.0.15// +//YaSSL doesn't support TLSv1.2, so if MariaDB server is build from sources with YaSSL, only TLSv1 and TLSv1.1 will be +available, even for version > 10.0.15// TLSv1.2 can be enabled by setting option {{{enabledSslProtocolSuites}}} to values {{{"TLSv1, TLSv1.1, TLSv1.2"}}}. A new option {{{enabledSslCipherSuites}}} permit setting specific cipher. New Options : -|=enabledSslProtocolSuites|Force TLS/SSL protocol to a specific set of TLS versions (comma separated list).
Example : "TLSv1, TLSv1.1, TLSv1.2"
//Default: TLSv1, TLSv1.1. Since 1.5.0//| -|=enabledSslCipherSuites|Force TLS/SSL cipher (comma separated list).
Example : "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
//Default: use JRE ciphers. Since 1.5.0//| +|=enabledSslProtocolSuites|Force TLS/SSL protocol to a specific set of TLS versions (comma separated list).
+Example : "TLSv1, TLSv1.1, TLSv1.2"
//Default: TLSv1, TLSv1.1. Since 1.5.0//| +|=enabledSslCipherSuites|Force TLS/SSL cipher (comma separated list).
Example : " +TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
//Default: use JRE ciphers. Since +1.5.0//| ### Performance improvement + [CONJ-291]
Different performance improvement have been done : -* Using PreparedStatement on client side use a simple query parser to identify query parameters. This parsing was taking up to 7% of query time, reduced to 3%. + +* Using PreparedStatement on client side use a simple query parser to identify query parameters. This parsing was taking + up to 7% of query time, reduced to 3%. * Better UTF-8 decoding avoiding memory consumption and gain 1-2% query time for big String. -* client parsing optimization : rewriteBatchedStatements (insert into ab (i) values (1) and insert into ab (i) values (2) rewritten as insert into ab (i) values (1), (2)) - is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to contain query). +* client parsing optimization : rewriteBatchedStatements (insert into ab (i) values (1) and insert into ab (i) values ( + 2) rewritten as insert into ab (i) values (1), (2)) + is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to + contain + query). * there was some memory wastage when query return big resultset (> 10kb), slowing query. * ... @@ -1052,13 +1205,17 @@ Send X well established MySQL protocol without reading results, and read those X Basically that permit to avoid a lot of 'ping-pong' between driver and server. New Options : -|=useBatchMultiSend|PreparedStatement.executeBatch() will send many QUERY before reading result packets.//Default: true. Since 1.5.0//| -|=useBatchMultiSendNumber|When using useBatchMultiSend, indicate maximum query that can be sent at a time.
//Default: 100. Since 1.5.0//| +|=useBatchMultiSend|PreparedStatement.executeBatch() will send many QUERY before reading result packets.//Default: true. +Since 1.5.0//| +|=useBatchMultiSendNumber|When using useBatchMultiSend, indicate maximum query that can be sent at a time.
+//Default: 100. Since 1.5.0//| ### Prepare + execute in one call + CONJ-296 When using MySQL/MariaDB prepared statement, there will be 3 exchanges with server : + * PREPARE - Prepares statement for execution. * EXECUTE - Executes a prepared statement preparing by a PREPARE statement. * DEALLOCATE PREPARE - Releases a prepared statement. @@ -1067,7 +1224,8 @@ See [Server prepare documentation](https://mariadb.com/kb/en/mariadb/prepare-sta information. PREPARE and DEALLOCATE PREPARE are 2 additional client-server round-trip. -Since MariaDB 10.2, a new functionality named COM-MULTI to permitting to send different task to server in one round-trip. +Since MariaDB 10.2, a new functionality named COM-MULTI to permitting to send different task to server in one +round-trip. Driver is using this functionality to PREPARE and EXECUTE in one client-server round-trip. ### Client logging @@ -1077,24 +1235,33 @@ This implementation need the standard SLF4J dependency. New Options : |=log|Enable log information. require Slf4j version > 1.4 dependency.
//Default: false. Since 1.5.0//| -|=maxQuerySizeToLog|Only the first characters corresponding to this options size will be displayed in logs
//Default: 1024. Since 1.5.0//| -|=slowQueryThresholdNanos|Will log query with execution time superior to this value (if defined )
//Default: 1024. Since 1.5.0//| +|=maxQuerySizeToLog|Only the first characters corresponding to this options size will be displayed in logs
+//Default: 1024. Since 1.5.0//| +|=slowQueryThresholdNanos|Will log query with execution time superior to this value (if defined )
//Default: 1024. +Since 1.5.0//| |=profileSql|log query execution time.
//Default: false. Since 1.5.0//| - ### "LOAD DATA INFILE" Interceptors + CONJ-305 -LOAD DATA INFILE The fastest way to load many datas is using query [LOAD DATA INFILE](https://mariadb.com/kb/en/mariadb/load-data-infile/). +LOAD DATA INFILE The fastest way to load many datas is using +query [LOAD DATA INFILE](https://mariadb.com/kb/en/mariadb/load-data-infile/).
Problem is using "LOAD DATA LOCAL INFILE" (ie : loading a file from client), may be a security problem : -* A "man in the middle" proxy server can change the actual file asked from server so client will send a Local file to this proxy. -* If someone has can execute query from client, he can have access to any file on client (according to the rights of the user running the client process). -See [load-data-infile documentation](./documentation/use-mariadb-connector-j-driver.creole#load-data-infile) for more information. +* A "man in the middle" proxy server can change the actual file asked from server so client will send a Local file to + this proxy. +* If someone has can execute query from client, he can have access to any file on client (according to the rights of the + user running the client process). + +See [load-data-infile documentation](./documentation/use-mariadb-connector-j-driver.creole#load-data-infile) for more +information. Interceptors can now filter LOAD DATA LOCAL INFILE query's file location to validate path / file name. Those interceptors: + * Must implement interface {{{org.mariadb.jdbc.LocalInfileInterceptor}}}. -* Use [[http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html|ServiceLoader]] implementation, so interceptors classes must be listed in file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor. +* Use [[http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html|ServiceLoader]] implementation, so + interceptors classes must be listed in file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor. Example: {{{ @@ -1109,9 +1276,12 @@ return filePath.equals("/var/tmp/exchanges"); } } }}} -file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor must exist with content {{{org.project.LocalInfileInterceptorImpl}}}. +file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor must exist with content +{{{org.project.LocalInfileInterceptorImpl}}}. -You can get rid of defining the META-INF/services file using [[https://github.com/google/auto/tree/master/service|google auto-service]] framework, permitting to use annotation {{{@AutoService(LocalInfileInterceptor.class)}}} that will register the implementation as a service automatically. +You can get rid of defining the META-INF/services file +using [[https://github.com/google/auto/tree/master/service|google auto-service]] framework, permitting to use annotation +{{{@AutoService(LocalInfileInterceptor.class)}}} that will register the implementation as a service automatically. Using the previous example: {{{ @@ -1127,29 +1297,33 @@ return filePath.equals("/var/tmp/exchanges"); } }}} - - ### Minor evolution + * CONJ-260 : Add jdbc nString, nCharacterStream, nClob implementation ### Bugfix + * CONJ-316 : Wrong Exception thrown for ScrollType TYPE_SCROLL_INSENSITIVE * CONJ-298 : Error on Callable function exception when no parameter and space before parenthesis * CONJ-314 : Permit using Call with Statement / Prepare Statement


+ ## 1.4.6 + * CONJ-293] Permit named pipe connection without host * CONJ-309] Possible NPE on aurora when failover occur during connection initialisation * CONJ-312] NPE while loading a null from TIMESTAMP field using binary protocol * misc] batch with one parameter correction (using rewriteBatchedStatements option) ## 1.4.5 + * CONJ-297] Useless memory consumption when using Statement.setQueryTimeout * CONJ-294] PrepareStatement on master reconnection after a failover * CONJ-288] using SHOW VARIABLES to replace SELECT on connection to permit connection on a galera non primary node * CONJ-290] Timestamps format error when using prepareStatement with options useFractionalSeconds and useServerPrepStmts ## 1.4.4 + * CONJ-289] PrepareStatement on master reconnection after a failover * CONJ-288] using SHOW VARIABLES to replace SELECT on connection to permit connection on a galera non primary node @@ -1165,73 +1339,91 @@ return filePath.equals("/var/tmp/exchanges"); * CONJ-275] Streaming result without result throw "Current position is before the first row" - ## 1.4.1 - * CONJ-274] correction to permit connection to MySQL 5.1 server * CONJ-273] correction when using prepareStatement without parameters and option rewriteBatchedStatements to true * CONJ-270] permit 65535 parameters to server preparedStatement * CONJ-268] update license header -* misc] when option rewriteBatchedStatements is set to true, correction of packet separation when query size > max_allow_packet +* misc] when option rewriteBatchedStatements is set to true, correction of packet separation when query size > + max_allow_packet * misc] performance improvement for select result. ## 1.4.0 ### Complete implementation of fetch size. + CONJ-26 JDBC allows to specify the number of rows fetched for a query, and this number is referred to as the fetch size Before version 1.4.0, query were loading all results or row by row using Statement.setFetchSize(Integer.MIN_VALUE). Now it's possible to set fetch size according to your need. -Loading all results for large result sets is using a lot of memory. This functionality permit to save memory without having performance decrease. +Loading all results for large result sets is using a lot of memory. This functionality permit to save memory without +having performance decrease. ### Memory footprint improvement + CONJ-125 Buffers have been optimized to reduced memory footprint ### CallableStatement performance improvement. + CONJ-209 -Calling function / procedure performance is now optimized according to query. Depending on queries, difference can be up to 300%. +Calling function / procedure performance is now optimized according to query. Depending on queries, difference can be up +to 300%. ### Authentication evolution -CONJ-251 Permit now new authentication possibility : [[https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/|PAM authentication]], and GSSAPI/SSPI authentication. + +CONJ-251 Permit now new authentication +possibility : [[https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/|PAM authentication]], and GSSAPI/SSPI +authentication. GSSAPI/SSPI authentication authentication plugin for MariaDB permit a passwordless login. -On Unix systems, GSSAPI is usually synonymous with Kerberos authentication. Windows has slightly different but very similar API called SSPI, that along with Kerberos, also supports NTLM authentication. -See more detail in [[https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/documentation/plugin/GSSAPI|GSSAPI/SSPI configuration]] +On Unix systems, GSSAPI is usually synonymous with Kerberos authentication. Windows has slightly different but very +similar API called SSPI, that along with Kerberos, also supports NTLM authentication. +See more detail +in [[https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/documentation/plugin/GSSAPI|GSSAPI/SSPI configuration]] ### Connection attributes + CONJ-217 -Driver information informations are now send to [[https://mariadb.com/kb/en/mariadb/performance-schema-session_connect_attrs-table/|connection attributes tables]] (performance_schema must be activated). +Driver information informations are now send +to [[https://mariadb.com/kb/en/mariadb/performance-schema-session_connect_attrs-table/|connection attributes tables]] ( +performance_schema must be activated). A new option "connectionAttributes" permit to add client specifics data. -For example when connecting with the following connection string {{{"jdbc:mariadb://localhost:3306/testj?user=root&connectionAttributes=myOption:1,mySecondOption:'jj'"}}}, -if performance_schema is activated, information about this connection will be available during the time this connection is active : +For example when connecting with the following connection string {{{"jdbc:mariadb://localhost: +3306/testj?user=root&connectionAttributes=myOption:1,mySecondOption:'jj'"}}}, +if performance_schema is activated, information about this connection will be available during the time this connection +is active : {{{ select * from performance_schema.session_connect_attrs where processList_id = 5 +----------------+-----------------+---------------------+------------------+ -| PROCESSLIST_ID | ATTR_NAME | ATTR_VALUE | ORDINAL_POSITION | +| PROCESSLIST_ID | ATTR_NAME | ATTR_VALUE | ORDINAL_POSITION | +----------------+-----------------+---------------------+------------------+ -|5 |_client_name |MariaDB connector/J |0 | -|5 |_client_version |1.4.0-SNAPSHOT |1 | -|5 |_os |Windows 8.1 |2 | -|5 |_pid |14124@portable-diego |3 | -|5 |_thread |5 |4 | -|5 |_java_vendor |Oracle Corporation |5 | -|5 |_java_version |1.7.0_79 |6 | -|5 |myOption |1 |7 | -|5 |mySecondOption |'jj' |8 | +|5 |_client_name |MariaDB connector/J |0 | +|5 |_client_version |1.4.0-SNAPSHOT |1 | +|5 |_os |Windows 8.1 |2 | +|5 |_pid |14124@portable-diego |3 | +|5 |_thread |5 |4 | +|5 |_java_vendor |Oracle Corporation |5 | +|5 |_java_version |1.7.0_79 |6 | +|5 |myOption |1 |7 | +|5 |mySecondOption |'jj' |8 | +----------------+-----------------+---------------------+------------------+ }}} - ## Minor evolution + * CONJ-210 : adding a "jdbcCompliantTruncation" option to force truncation warning as SQLException. -* CONJ-211 : when in master/slave configuration, option "assureReadOnly" will ensure that slaves are in read-only mode ( forcing transaction by a query "SET SESSION TRANSACTION READ ONLY"). -* CONJ-213 : new option "continueBatchOnError". Permit to continue batch when an exception occur : When executing a batch and an error occur, must the batch stop immediatly (default) or finish remaining batch before throwing exception. +* CONJ-211 : when in master/slave configuration, option "assureReadOnly" will ensure that slaves are in read-only mode ( + forcing transaction by a query "SET SESSION TRANSACTION READ ONLY"). +* CONJ-213 : new option "continueBatchOnError". Permit to continue batch when an exception occur : When executing a + batch and an error occur, must the batch stop immediatly (default) or finish remaining batch before throwing + exception. ## Bugfix + * CONJ-236 : Using a parametrized query with a smallint -1 does return the unsigned value * CONJ-250 : Tomcat doesn't stop when using Aurora failover configuration * CONJ-260 : Add jdbc nString, nCharacterStream, nClob implementation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 952fe34a2..94240c3d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,70 +1,80 @@ # Contributing -Each pull request should address a single issue, and contain both the fix and a description of how the pull request and tests that validate that the PR fixes the issue in question. +Each pull request should address a single issue, and contain both the fix and a description of how the pull request and +tests that validate that the PR fixes the issue in question. -For significant feature additions, we like to have an open issue in [MariaDB JIRA](https://mariadb.atlassian.net/secure/RapidBoard.jspa?projectKey=CONJ). It is expected that discussion will have taken place in the attached issue. +For significant feature additions, we like to have an open issue +in [MariaDB JIRA](https://mariadb.atlassian.net/secure/RapidBoard.jspa?projectKey=CONJ). It is expected that discussion +will have taken place in the attached issue. # Install Prerequisites -These are the set of tools which are required in order to complete any build. Follow the links to download and install them on your own before continuing. +These are the set of tools which are required in order to complete any build. Follow the links to download and install +them on your own before continuing. * At least one GPG Key see https://help.github.com/en/articles/generating-a-new-gpg-key -* [Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) ( with [JCE policies](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) if using TLS/SSL) +* [Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) ( + with [JCE policies](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) if using + TLS/SSL) * IDE (eclipse / netbean / intelliJ) with maven and GIT plugins # Fork source -Before downloading source, fork the project to your own repository, and use your repository as source. +Before downloading source, fork the project to your own repository, and use your repository as source. ## Branch signification * master : correspond to the last released version * develop : Develop new features for upcoming releases (compatible with java 8) -* develop-jre6 : maintenance branch compatible with java 6 / 7 +* develop-jre6 : maintenance branch compatible with java 6 / 7 # Run local test Before any submission : -Run the test locally : by default, you need to have a MySQL/MariaDB server on localhost:3306 with a database named "testj" and a user root without password. -so you can run - +Run the test locally : by default, you need to have a MySQL/MariaDB server on localhost:3306 with a database named " +testj" and a user root without password. +so you can run + ```script mvn test ``` - -You can change this parameter by adding -DdbUrl parameter. like : - + +You can change this parameter by adding -DdbUrl parameter. like : + ```script mvn test -DdbUrl=jdbc:mariadb://127.0.0.1:3306/testj?user=root&password=***** ``` - + You can launch a specific test by adding -Dtest ```script mvn test -Dtest=org.mariadb.jdbc.JdbcParserTest ``` - + When all test are passing, you can package project. -Additional tests , like javadoc formatting, code style validation will be done : - +Additional tests , like javadoc formatting, code style validation will be done : + ```script mvn package -Dmaven.test.skip=true ``` - + If operation succeed, a new mariadb-java-client jar will be on the target folder. - + # Run travis test - -You can activate travis to validate your repository. -The advantage of travis compare to running test locally is that it will launch tests for a combination of those parameters : + +You can activate travis to validate your repository. +The advantage of travis compare to running test locally is that it will launch tests for a combination of those +parameters : jdk: + * oraclejdk8 -and if your work is on develop-jre6 branch + and if your work is on develop-jre6 branch * openjdk6 * openjdk7 server : + * MariaDB 5.5 * MariaDB 10.0 * MariaDB 10.1 @@ -73,17 +83,20 @@ server : * MySQL 5.7 max_allowed_packet : (this permit to check multipacket send) + * 8M * 20M * 40M -For that, you have to go on [travis website](https://travis-ci.org), connect with your github account, and activate your mariadb-connector-j repository. -After this step, every push to your repository will launch a travis test. +For that, you have to go on [travis website](https://travis-ci.org), connect with your github account, and activate your +mariadb-connector-j repository. +After this step, every push to your repository will launch a travis test. ## Submitting a request -When your repository has the correction/change done, you can submit a pull request by clicking the "Pull request" button on github. -Please detail the operation done in your request. +When your repository has the correction/change done, you can submit a pull request by clicking the "Pull request" button +on github. +Please detail the operation done in your request. ## License diff --git a/README.md b/README.md index bfc94ef93..a5d30f2d0 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ -

+

- + mariadb logo

# MariaDB java connector -MariaDB java connector is a JDBC 4.2 compatible driver, used to connect applications developed in Java to MariaDB and MySQL databases. MariaDB Connector/J is LGPL licensed. +MariaDB java connector is a JDBC 4.2 compatible driver, used to connect applications developed in Java to MariaDB and +MySQL databases. MariaDB Connector/J is LGPL licensed. Tracker link https://jira.mariadb.org/projects/CONJ/issues/ ## Status + [![Linux Build](https://travis-ci.com/mariadb-corporation/mariadb-connector-j.svg?branch=master)](https://app.travis-ci.com/github/mariadb-corporation/mariadb-connector-j) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mariadb.jdbc/mariadb-java-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mariadb.jdbc/mariadb-java-client) [![License (LGPL version 2.1)](https://img.shields.io/badge/license-GNU%20LGPL%20version%202.1-green.svg?style=flat-square)](http://opensource.org/licenses/LGPL-2.1) @@ -21,7 +23,8 @@ Tracker link https://ji For java 8+ : The driver (jar) can be downloaded from [mariadb connector download](https://mariadb.com/downloads/#connectors) -or maven : +or maven : + ```script org.mariadb.jdbc @@ -30,8 +33,8 @@ or maven : ``` - Development snapshot are available on sonatype nexus repository + ```script @@ -52,12 +55,13 @@ Development snapshot are available on sonatype nexus repository ## Documentation -For a Getting started guide, API docs, recipes, etc. see the +For a Getting started guide, API docs, recipes, etc. see the + * [About MariaDB connector/J](https://mariadb.com/kb/en/about-mariadb-connector-j/) * [Install driver](https://mariadb.com/kb/en/installing-mariadb-connectorj/) * [Changelog](/CHANGELOG.md) * [Failover and high-availability](https://mariadb.com/kb/en/failover-and-high-availability-with-mariadb-connector-j/) - [codecov-image]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-j/branch/master/graph/badge.svg + [codecov-url]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-j diff --git a/pom.xml b/pom.xml index aa96a8e41..9624bddda 100644 --- a/pom.xml +++ b/pom.xml @@ -231,20 +231,30 @@
- - com.spotify.fmt - fmt-maven-plugin - 2.20 + com.theoryinpractise + googleformatter-maven-plugin + 1.7.3 + reformat-sources + + false + + true + true + false + false + false + 100 + format + process-sources - org.apache.maven.plugins maven-surefire-plugin diff --git a/src/benchmark/README.md b/src/benchmark/README.md index 1a5158f14..ca7eedd74 100644 --- a/src/benchmark/README.md +++ b/src/benchmark/README.md @@ -1,12 +1,13 @@ -

+

- + mariadb logo

# Benchmark -How to run : +How to run : + ```script mvn clean package -P bench -DskipTests @@ -18,6 +19,7 @@ java -Duser.country=US -Duser.language=en -jar target/benchmarks.jar "Select_100 ``` Configuration by system properties : + * TEST_HOST: Hostname. default "localhost" * TEST_PORT: port. default 3306 * TEST_USERNAME: user name. default "root" @@ -25,7 +27,8 @@ Configuration by system properties : * TEST_DATABASE: database. default "testj" * TEST_OTHER: permit adding connection string options. default "" -example: +example: + ```script mvn clean package -P bench -Dmaven.test.skip java -DTEST_PORT=3307 -Duser.country=US -Duser.language=en -jar target/benchmarks.jar "Select_100_cols" diff --git a/src/benchmark/java/org/mariadb/jdbc/Common.java b/src/benchmark/java/org/mariadb/jdbc/Common.java index 9d68aee58..bd4e3b3f6 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Common.java +++ b/src/benchmark/java/org/mariadb/jdbc/Common.java @@ -4,14 +4,13 @@ package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.*; - import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; @State(Scope.Benchmark) @Warmup(iterations = 10, timeUnit = TimeUnit.SECONDS, time = 1) diff --git a/src/benchmark/java/org/mariadb/jdbc/Do_1.java b/src/benchmark/java/org/mariadb/jdbc/Do_1.java index 7b23d008e..833f7bf0e 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Do_1.java +++ b/src/benchmark/java/org/mariadb/jdbc/Do_1.java @@ -11,11 +11,10 @@ public class Do_1 extends Common { - @Benchmark - public int run(MyState state) throws Throwable { - try (Statement st = state.connectionText.createStatement()) { - return st.executeUpdate("DO 1"); - } + @Benchmark + public int run(MyState state) throws Throwable { + try (Statement st = state.connectionText.createStatement()) { + return st.executeUpdate("DO 1"); } - + } } diff --git a/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java b/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java index 0c6e157b6..95e4850b9 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java +++ b/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java @@ -4,11 +4,9 @@ package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; +import org.openjdk.jmh.annotations.Benchmark; public class Do_1000_params extends Common { diff --git a/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java b/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java index 7b9ebbcba..a55166f31 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java +++ b/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java @@ -4,15 +4,12 @@ package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.openjdk.jmh.annotations.Benchmark; public class Insert_batch extends Common { diff --git a/src/benchmark/java/org/mariadb/jdbc/Select_1.java b/src/benchmark/java/org/mariadb/jdbc/Select_1.java index 4a5a63815..dce05b6e3 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Select_1.java +++ b/src/benchmark/java/org/mariadb/jdbc/Select_1.java @@ -4,10 +4,9 @@ package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.ResultSet; import java.sql.Statement; +import org.openjdk.jmh.annotations.Benchmark; public class Select_1 extends Common { diff --git a/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java b/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java index a1848381c..f9891ee6f 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java +++ b/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java @@ -4,11 +4,10 @@ package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import org.openjdk.jmh.annotations.Benchmark; public class Select_1000_Rows extends Common { private static final String sql = diff --git a/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java b/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java index a4f5a03a8..27397ea9d 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java +++ b/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java @@ -4,13 +4,9 @@ package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - import java.sql.*; import java.sql.Connection; -import java.sql.Statement; +import org.openjdk.jmh.annotations.Benchmark; public class Select_100_cols extends Common { diff --git a/src/benchmark/resources/logback-test.xml b/src/benchmark/resources/logback-test.xml index 3dbbecb7a..4a424742f 100644 --- a/src/benchmark/resources/logback-test.xml +++ b/src/benchmark/resources/logback-test.xml @@ -1,17 +1,17 @@ - - - %d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %5p | %logger{25} | %m%n - - - + + + %d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %5p | %logger{25} | %m%n + + + - + - - - + + + \ No newline at end of file diff --git a/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java b/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java index 2a9516ae1..2ad2379f1 100644 --- a/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java +++ b/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java @@ -28,12 +28,12 @@ public abstract class BaseCallableStatement extends ServerPreparedStatement /** Procedure name */ protected final String procedureName; - /** parameter metadata */ - protected CallableParameterMetaData parameterMetaData = null; - /** Declared output parameters */ protected final Set outputParameters = new HashSet<>(); + /** parameter metadata */ + protected CallableParameterMetaData parameterMetaData = null; + /** output parameter result */ private Result outputResult = null; diff --git a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java index 0d0ec46ea..0f760afc2 100644 --- a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java @@ -26,7 +26,10 @@ /** Common methods for prepare statement, for client and server prepare statement. */ public abstract class BasePreparedStatement extends Statement implements PreparedStatement { private static final Pattern INSERT_STATEMENT_PATTERN = - Pattern.compile("^(\\s*\\/\\*([^*]|\\*[^/])*\\*\\/)*\\s*(INSERT)", Pattern.CASE_INSENSITIVE); + Pattern.compile("^(\\s*/\\*([^*]|\\*[^/])*\\*/)*\\s*(INSERT)", Pattern.CASE_INSENSITIVE); + + /** prepare statement sql command */ + protected final String sql; /** parameters */ protected Parameters parameters; @@ -34,9 +37,6 @@ public abstract class BasePreparedStatement extends Statement implements Prepare /** batching parameters */ protected List batchParameters; - /** prepare statement sql command */ - protected final String sql; - /** PREPARE command result */ protected Prepare prepareResult = null; @@ -98,7 +98,7 @@ public String toString() { protected void checkIfInsertCommand() { if (isCommandInsert == null) - isCommandInsert = (sql == null) ? false : INSERT_STATEMENT_PATTERN.matcher(sql).find(); + isCommandInsert = sql != null && INSERT_STATEMENT_PATTERN.matcher(sql).find(); } /** @@ -1145,13 +1145,13 @@ private void setInternalObject( return; case Types.DOUBLE: case Types.FLOAT: - setDouble(parameterIndex, Double.valueOf(str)); + setDouble(parameterIndex, Double.parseDouble(str)); return; case Types.REAL: - setFloat(parameterIndex, Float.valueOf(str)); + setFloat(parameterIndex, Float.parseFloat(str)); return; case Types.BIGINT: - setLong(parameterIndex, Long.valueOf(str)); + setLong(parameterIndex, Long.parseLong(str)); return; case Types.DECIMAL: case Types.NUMERIC: @@ -1175,7 +1175,7 @@ private void setInternalObject( } return; case Types.TIME: - setTime(parameterIndex, Time.valueOf((String) obj)); + setTime(parameterIndex, Time.valueOf(str)); return; default: throw exceptionFactory() diff --git a/src/main/java/org/mariadb/jdbc/Configuration.java b/src/main/java/org/mariadb/jdbc/Configuration.java index a43153168..3521b0952 100644 --- a/src/main/java/org/mariadb/jdbc/Configuration.java +++ b/src/main/java/org/mariadb/jdbc/Configuration.java @@ -760,6 +760,266 @@ private static HaMode parseHaMode(String url, int separator) { } } + /** + * Permit to have string information on how string is parsed. example : + * Configuration.toConf("jdbc:mariadb://localhost/test") will return a String containing: + * Configuration: + * * resulting Url : jdbc:mariadb://localhost/test + * Unknown options : None + * + * Non default options : + * * database : test + * + * default options : + * * user : null + * ... + * + * + * @param url url string + * @return string describing the configuration parsed from url + * @throws SQLException if parsing fails + */ + public static String toConf(String url) throws SQLException { + Configuration conf = Configuration.parseInternal(url, new Properties()); + StringBuilder sb = new StringBuilder(); + StringBuilder sbUnknownOpts = new StringBuilder(); + + if (conf.nonMappedOptions.isEmpty()) { + sbUnknownOpts.append("None"); + } else { + for (Map.Entry entry : conf.nonMappedOptions.entrySet()) { + sbUnknownOpts.append("\n * ").append(entry.getKey()).append(" : ").append(entry.getValue()); + } + } + sb.append("Configuration:") + .append("\n * resulting Url : ") + .append(conf.initialUrl) + .append("\nUnknown options : ") + .append(sbUnknownOpts) + .append("\n") + .append("\nNon default options : "); + + Configuration defaultConf = Configuration.parse("jdbc:mariadb://localhost/"); + StringBuilder sbDefaultOpts = new StringBuilder(); + StringBuilder sbDifferentOpts = new StringBuilder(); + try { + List propertyToSkip = Arrays.asList("initialUrl", "logger", "codecs", "$jacocoData"); + Field[] fields = Configuration.class.getDeclaredFields(); + Arrays.sort(fields, Comparator.comparing(Field::getName)); + + for (Field field : fields) { + if (!propertyToSkip.contains(field.getName())) { + Object fieldValue = field.get(conf); + if (fieldValue == null) { + (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + } else { + if (field.getName().equals("haMode")) { + (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + continue; + } + switch (fieldValue.getClass().getSimpleName()) { + case "String": + case "Boolean": + case "HaMode": + case "TransactionIsolation": + case "Integer": + case "SslMode": + case "CatalogTerm": + (Objects.equals(fieldValue, field.get(defaultConf)) + ? sbDefaultOpts + : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + break; + case "ArrayList": + (Objects.equals(fieldValue.toString(), field.get(defaultConf).toString()) + ? sbDefaultOpts + : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + break; + case "Properties": + break; + default: + throw new IllegalArgumentException( + "field type not expected for fields " + field.getName()); + } + } + } + } + + String diff = sbDifferentOpts.toString(); + if (diff.isEmpty()) { + sb.append("None\n"); + } else { + sb.append(diff); + } + + sb.append("\n\ndefault options :"); + String same = sbDefaultOpts.toString(); + if (same.isEmpty()) { + sb.append("None\n"); + } else { + sb.append(same); + } + + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new IllegalArgumentException("Wrong parsing", e); + } + return sb.toString(); + } + + /** + * Generate initialURL property + * + * @param conf current configuration + * @return initialUrl value. + */ + protected static String buildUrl(Configuration conf) { + Configuration defaultConf = new Configuration(); + StringBuilder sb = new StringBuilder(); + sb.append("jdbc:mariadb:"); + if (conf.haMode != HaMode.NONE) { + sb.append(conf.haMode.toString().toLowerCase(Locale.ROOT)).append(":"); + } + sb.append("//"); + for (int i = 0; i < conf.addresses.size(); i++) { + HostAddress hostAddress = conf.addresses.get(i); + if (i > 0) { + sb.append(","); + } + if ((conf.haMode == HaMode.NONE && hostAddress.primary) + || (conf.haMode == HaMode.REPLICATION + && ((i == 0 && hostAddress.primary) || (i != 0 && !hostAddress.primary)))) { + sb.append(hostAddress.host); + if (hostAddress.port != 3306) sb.append(":").append(hostAddress.port); + } else { + sb.append("address=(host=") + .append(hostAddress.host) + .append(")") + .append("(port=") + .append(hostAddress.port) + .append(")"); + sb.append("(type=").append(hostAddress.primary ? "primary" : "replica").append(")"); + } + } + + sb.append("/"); + if (conf.database != null) { + sb.append(conf.database); + } + + try { + // Option object is already initialized to default values. + // loop on properties, + // - check DefaultOption to check that property value correspond to type (and range) + // - set values + boolean first = true; + + Field[] fields = Configuration.class.getDeclaredFields(); + for (Field field : fields) { + if ("database".equals(field.getName()) + || "haMode".equals(field.getName()) + || "$jacocoData".equals(field.getName()) + || "addresses".equals(field.getName())) { + continue; + } + Object obj = field.get(conf); + + if (obj != null && (!(obj instanceof Properties) || ((Properties) obj).size() > 0)) { + + if ("password".equals(field.getName())) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append("***"); + continue; + } + + if (field.getType().equals(String.class)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append((String) obj); + } else if (field.getType().equals(boolean.class)) { + boolean defaultValue = field.getBoolean(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append(obj); + } + } else if (field.getType().equals(int.class)) { + try { + int defaultValue = field.getInt(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + sb.append(field.getName()).append('=').append(obj); + first = false; + } + } catch (IllegalAccessException n) { + // eat + } + } else if (field.getType().equals(Properties.class)) { + sb.append(first ? '?' : '&'); + first = false; + boolean firstProp = true; + Properties properties = (Properties) obj; + for (Object key : properties.keySet()) { + if (firstProp) { + firstProp = false; + } else { + sb.append('&'); + } + sb.append(key).append('='); + sb.append(properties.get(key)); + } + } else if (field.getType().equals(CredentialPlugin.class)) { + Object defaultValue = field.get(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append(((CredentialPlugin) obj).type()); + } + } else { + Object defaultValue = field.get(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append(obj); + } + } + } + } + + } catch (IllegalAccessException n) { + n.printStackTrace(); + } catch (SecurityException s) { + // only for jws, so never thrown + throw new IllegalArgumentException("Security too restrictive : " + s.getMessage()); + } + conf.loadCodecs(); + return sb.toString(); + } + + private static String nullOrEmpty(String val) { + return (val == null || val.isEmpty()) ? null : val; + } + /** * Clone configuration with another user/password * @@ -1472,387 +1732,130 @@ public boolean registerJmxPool() { * Pool mininum validation delay. * * @return pool validation delay - */ - public int poolValidMinDelay() { - return poolValidMinDelay; - } - - /** - * Must connection returned to pool be RESET - * - * @return use RESET on connection - */ - public boolean useResetConnection() { - return useResetConnection; - } - - /** - * Server RSA public key file for caching_sha2_password authentication - * - * @return server key file - */ - public String serverRsaPublicKeyFile() { - return serverRsaPublicKeyFile; - } - - /** - * permit mysql authentication to retrieve server certificate - * - * @return is driver allowed to retrieve server certificate from server - */ - public boolean allowPublicKeyRetrieval() { - return allowPublicKeyRetrieval; - } - - /** - * Read all data from socket in advance - * - * @return use read ahead buffer implementation - */ - public boolean useReadAheadInput() { - return useReadAheadInput; - } - - /** - * Cache prepared statement result. - * - * @return cache prepare results - */ - public boolean cachePrepStmts() { - return cachePrepStmts; - } - - /** - * implements transaction replay failover - * - * @return true if transaction must be replayed on failover. - */ - public boolean transactionReplay() { - return transactionReplay; - } - - /** - * transaction replay maximum number of saved command. - * - * @return transaction replay buffer size. - */ - public int transactionReplaySize() { - return transactionReplaySize; - } - - /** - * geometry default decoding implementation - * - * @return geometry default type - */ - public String geometryDefaultType() { - return geometryDefaultType; - } - - /** - * Restrict authentication plugin to comma separated plugin list - * - * @return authorized authentication list - */ - public String restrictedAuth() { - return restrictedAuth; - } - - /** - * Execute initial command when connection is established - * - * @return initial SQL command - */ - public String initSql() { - return initSql; - } - - /** - * datatype Encoder/decoder list - * - * @return codec list - */ - public Codec[] codecs() { - return codecs; - } - - /** - * ToString implementation. - * - * @return String value - */ - public String toString() { - return initialUrl; - } - - /** - * Permit to have string information on how string is parsed. example : - * Configuration.toConf("jdbc:mariadb://localhost/test") will return a String containing: - * Configuration: - * * resulting Url : jdbc:mariadb://localhost/test - * Unknown options : None - * - * Non default options : - * * database : test - * - * default options : - * * user : null - * ... - * - * - * @param url url string - * @return string describing the configuration parsed from url - * @throws SQLException if parsing fails - */ - public static String toConf(String url) throws SQLException { - Configuration conf = Configuration.parseInternal(url, new Properties()); - StringBuilder sb = new StringBuilder(); - StringBuilder sbUnknownOpts = new StringBuilder(); - - if (conf.nonMappedOptions.isEmpty()) { - sbUnknownOpts.append("None"); - } else { - for (Map.Entry entry : conf.nonMappedOptions.entrySet()) { - sbUnknownOpts.append("\n * ").append(entry.getKey()).append(" : ").append(entry.getValue()); - } - } - sb.append("Configuration:") - .append("\n * resulting Url : ") - .append(conf.initialUrl) - .append("\nUnknown options : ") - .append(sbUnknownOpts) - .append("\n") - .append("\nNon default options : "); - - Configuration defaultConf = Configuration.parse("jdbc:mariadb://localhost/"); - StringBuilder sbDefaultOpts = new StringBuilder(); - StringBuilder sbDifferentOpts = new StringBuilder(); - try { - List propertyToSkip = - Arrays.asList(new String[] {"initialUrl", "logger", "codecs", "$jacocoData"}); - Field[] fields = Configuration.class.getDeclaredFields(); - Arrays.sort(fields, Comparator.comparing(Field::getName)); - - for (Field field : fields) { - if (!propertyToSkip.contains(field.getName())) { - Object fieldValue = field.get(conf); - if (fieldValue == null) { - (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - } else { - if (field.getName().equals("haMode")) { - (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - continue; - } - switch (fieldValue.getClass().getSimpleName()) { - case "String": - case "Boolean": - case "HaMode": - case "TransactionIsolation": - case "Integer": - case "SslMode": - case "CatalogTerm": - (Objects.equals(fieldValue, field.get(defaultConf)) - ? sbDefaultOpts - : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - break; - case "ArrayList": - (Objects.equals(fieldValue.toString(), field.get(defaultConf).toString()) - ? sbDefaultOpts - : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - break; - case "Properties": - break; - default: - throw new IllegalArgumentException( - "field type not expected for fields " + field.getName()); - } - } - } - } + */ + public int poolValidMinDelay() { + return poolValidMinDelay; + } - String diff = sbDifferentOpts.toString(); - if (diff.isEmpty()) { - sb.append("None\n"); - } else { - sb.append(diff); - } + /** + * Must connection returned to pool be RESET + * + * @return use RESET on connection + */ + public boolean useResetConnection() { + return useResetConnection; + } - sb.append("\n\ndefault options :"); - String same = sbDefaultOpts.toString(); - if (same.isEmpty()) { - sb.append("None\n"); - } else { - sb.append(same); - } + /** + * Server RSA public key file for caching_sha2_password authentication + * + * @return server key file + */ + public String serverRsaPublicKeyFile() { + return serverRsaPublicKeyFile; + } - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new IllegalArgumentException("Wrong parsing", e); - } - return sb.toString(); + /** + * permit mysql authentication to retrieve server certificate + * + * @return is driver allowed to retrieve server certificate from server + */ + public boolean allowPublicKeyRetrieval() { + return allowPublicKeyRetrieval; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + /** + * Read all data from socket in advance + * + * @return use read ahead buffer implementation + */ + public boolean useReadAheadInput() { + return useReadAheadInput; + } - Configuration that = (Configuration) o; + /** + * Cache prepared statement result. + * + * @return cache prepare results + */ + public boolean cachePrepStmts() { + return cachePrepStmts; + } - if (password == null) { - return initialUrl.equals(that.initialUrl) && that.password == null; - } - return initialUrl.equals(that.initialUrl) && password.equals(that.password); + /** + * implements transaction replay failover + * + * @return true if transaction must be replayed on failover. + */ + public boolean transactionReplay() { + return transactionReplay; } /** - * Generate initialURL property + * transaction replay maximum number of saved command. * - * @param conf current configuration - * @return initialUrl value. + * @return transaction replay buffer size. */ - protected static String buildUrl(Configuration conf) { - Configuration defaultConf = new Configuration(); - StringBuilder sb = new StringBuilder(); - sb.append("jdbc:mariadb:"); - if (conf.haMode != HaMode.NONE) { - sb.append(conf.haMode.toString().toLowerCase(Locale.ROOT)).append(":"); - } - sb.append("//"); - for (int i = 0; i < conf.addresses.size(); i++) { - HostAddress hostAddress = conf.addresses.get(i); - if (i > 0) { - sb.append(","); - } - if ((conf.haMode == HaMode.NONE && hostAddress.primary) - || (conf.haMode == HaMode.REPLICATION - && ((i == 0 && hostAddress.primary) || (i != 0 && !hostAddress.primary)))) { - sb.append(hostAddress.host); - if (hostAddress.port != 3306) sb.append(":").append(hostAddress.port); - } else { - sb.append("address=(host=") - .append(hostAddress.host) - .append(")") - .append("(port=") - .append(hostAddress.port) - .append(")"); - sb.append("(type=").append(hostAddress.primary ? "primary" : "replica").append(")"); - } - } + public int transactionReplaySize() { + return transactionReplaySize; + } - sb.append("/"); - if (conf.database != null) { - sb.append(conf.database); - } + /** + * geometry default decoding implementation + * + * @return geometry default type + */ + public String geometryDefaultType() { + return geometryDefaultType; + } - try { - // Option object is already initialized to default values. - // loop on properties, - // - check DefaultOption to check that property value correspond to type (and range) - // - set values - boolean first = true; + /** + * Restrict authentication plugin to comma separated plugin list + * + * @return authorized authentication list + */ + public String restrictedAuth() { + return restrictedAuth; + } - Field[] fields = Configuration.class.getDeclaredFields(); - for (Field field : fields) { - if ("database".equals(field.getName()) - || "haMode".equals(field.getName()) - || "$jacocoData".equals(field.getName()) - || "addresses".equals(field.getName())) { - continue; - } - Object obj = field.get(conf); + /** + * Execute initial command when connection is established + * + * @return initial SQL command + */ + public String initSql() { + return initSql; + } - if (obj != null && (!(obj instanceof Properties) || ((Properties) obj).size() > 0)) { + /** + * datatype Encoder/decoder list + * + * @return codec list + */ + public Codec[] codecs() { + return codecs; + } - if ("password".equals(field.getName())) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append("***"); - continue; - } + /** + * ToString implementation. + * + * @return String value + */ + public String toString() { + return initialUrl; + } - if (field.getType().equals(String.class)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append((String) obj); - } else if (field.getType().equals(boolean.class)) { - boolean defaultValue = field.getBoolean(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append(obj); - } - } else if (field.getType().equals(int.class)) { - try { - int defaultValue = field.getInt(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - sb.append(field.getName()).append('=').append(obj); - first = false; - } - } catch (IllegalAccessException n) { - // eat - } - } else if (field.getType().equals(Properties.class)) { - sb.append(first ? '?' : '&'); - first = false; - boolean firstProp = true; - Properties properties = (Properties) obj; - for (Object key : properties.keySet()) { - if (firstProp) { - firstProp = false; - } else { - sb.append('&'); - } - sb.append(key).append('='); - sb.append(properties.get(key)); - } - } else if (field.getType().equals(CredentialPlugin.class)) { - Object defaultValue = field.get(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append(((CredentialPlugin) obj).type()); - } - } else { - Object defaultValue = field.get(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append(obj); - } - } - } - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; - } catch (IllegalAccessException n) { - n.printStackTrace(); - } catch (SecurityException s) { - // only for jws, so never thrown - throw new IllegalArgumentException("Security too restrictive : " + s.getMessage()); + Configuration that = (Configuration) o; + + if (password == null) { + return initialUrl.equals(that.initialUrl) && that.password == null; } - conf.loadCodecs(); - return sb.toString(); + return initialUrl.equals(that.initialUrl) && password.equals(that.password); } @SuppressWarnings("rawtypes") @@ -2971,8 +2974,4 @@ public Configuration build() throws SQLException { return conf; } } - - private static String nullOrEmpty(String val) { - return (val == null || val.isEmpty()) ? null : val; - } } diff --git a/src/main/java/org/mariadb/jdbc/Connection.java b/src/main/java/org/mariadb/jdbc/Connection.java index c3fcecdfa..6da292ea7 100644 --- a/src/main/java/org/mariadb/jdbc/Connection.java +++ b/src/main/java/org/mariadb/jdbc/Connection.java @@ -39,17 +39,17 @@ public class Connection implements java.sql.Connection { private final ReentrantLock lock; private final Configuration conf; - private ExceptionFactory exceptionFactory; private final Client client; private final Properties clientInfo = new Properties(); - private int lowercaseTableNames = -1; private final AtomicInteger savepointId = new AtomicInteger(); - private boolean readOnly; private final boolean canUseServerTimeout; private final boolean canCachePrepStmts; private final boolean canUseServerMaxRows; private final int defaultFetchSize; private final boolean forceTransactionEnd; + private ExceptionFactory exceptionFactory; + private int lowercaseTableNames = -1; + private boolean readOnly; private MariaDbPoolConnection poolConnection; /** @@ -803,55 +803,6 @@ public Client getClient() { return client; } - /** Internal Savepoint implementation */ - class MariaDbSavepoint implements java.sql.Savepoint { - - private final String name; - private final Integer id; - - public MariaDbSavepoint(final String name) { - this.name = name; - this.id = null; - } - - public MariaDbSavepoint(final int savepointId) { - this.id = savepointId; - this.name = null; - } - - /** - * Retrieves the generated ID for the savepoint that this Savepoint object - * represents. - * - * @return the numeric ID of this savepoint - */ - public int getSavepointId() throws SQLException { - if (name != null) { - throw exceptionFactory.create("Cannot retrieve savepoint id of a named savepoint"); - } - return id; - } - - /** - * Retrieves the name of the savepoint that this Savepoint object represents. - * - * @return the name of this savepoint - */ - public String getSavepointName() throws SQLException { - if (id != null) { - throw exceptionFactory.create("Cannot retrieve savepoint name of an unnamed savepoint"); - } - return name; - } - - public String rawValue() { - if (id != null) { - return "_jid_" + id; - } - return name; - } - } - /** * Reset connection set has it was after creating a "fresh" new connection. * defaultTransactionIsolation must have been initialized. @@ -891,7 +842,7 @@ && getContext().getVersion().getMinorVersion() == 2 setNetworkTimeout(null, conf.socketTimeout()); } if ((stateFlag & ConnectionState.STATE_AUTOCOMMIT) != 0) { - setAutoCommit(conf.autocommit() == null ? true : conf.autocommit()); + setAutoCommit(conf.autocommit() == null || conf.autocommit()); } if ((stateFlag & ConnectionState.STATE_DATABASE) != 0) { setCatalog(conf.database()); @@ -953,4 +904,53 @@ protected ExceptionFactory getExceptionFactory() { public String __test_host() { return this.client.getHostAddress().toString(); } + + /** Internal Savepoint implementation */ + class MariaDbSavepoint implements java.sql.Savepoint { + + private final String name; + private final Integer id; + + public MariaDbSavepoint(final String name) { + this.name = name; + this.id = null; + } + + public MariaDbSavepoint(final int savepointId) { + this.id = savepointId; + this.name = null; + } + + /** + * Retrieves the generated ID for the savepoint that this Savepoint object + * represents. + * + * @return the numeric ID of this savepoint + */ + public int getSavepointId() throws SQLException { + if (name != null) { + throw exceptionFactory.create("Cannot retrieve savepoint id of a named savepoint"); + } + return id; + } + + /** + * Retrieves the name of the savepoint that this Savepoint object represents. + * + * @return the name of this savepoint + */ + public String getSavepointName() throws SQLException { + if (id != null) { + throw exceptionFactory.create("Cannot retrieve savepoint name of an unnamed savepoint"); + } + return name; + } + + public String rawValue() { + if (id != null) { + return "_jid_" + id; + } + return name; + } + } } diff --git a/src/main/java/org/mariadb/jdbc/Driver.java b/src/main/java/org/mariadb/jdbc/Driver.java index e9e913d8a..3a19f5318 100644 --- a/src/main/java/org/mariadb/jdbc/Driver.java +++ b/src/main/java/org/mariadb/jdbc/Driver.java @@ -80,11 +80,6 @@ public static Connection connect(Configuration configuration) throws SQLExceptio return new Connection(configuration, lock, client); } - @FunctionalInterface - private interface ClientInstance { - R apply(T t, U u, V v, W w) throws SQLException; - } - /** * Connect to the given connection string. * @@ -186,4 +181,9 @@ public boolean jdbcCompliant() { public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException("Use logging parameters for enabling logging."); } + + @FunctionalInterface + private interface ClientInstance { + R apply(T t, U u, V v, W w) throws SQLException; + } } diff --git a/src/main/java/org/mariadb/jdbc/HostAddress.java b/src/main/java/org/mariadb/jdbc/HostAddress.java index 2a14bf066..53ffa01b2 100644 --- a/src/main/java/org/mariadb/jdbc/HostAddress.java +++ b/src/main/java/org/mariadb/jdbc/HostAddress.java @@ -12,16 +12,12 @@ /** Host entry */ public class HostAddress { - private long CONNECTED_VALUE_TIMEOUT = 3 * 60 * 1000; // 3 minutes /** host address */ public final String host; - /** port */ public int port; - /** primary node */ public Boolean primary; - private Long threadsConnected; private Long threadConnectedTimeout; @@ -194,15 +190,16 @@ public int hashCode() { return Objects.hash(host, port, primary); } - public void setThreadsConnected(long threadsConnected) { - this.threadsConnected = threadsConnected; - this.threadConnectedTimeout = System.currentTimeMillis() + CONNECTED_VALUE_TIMEOUT; - } - public Long getThreadsConnected() { return threadsConnected; } + public void setThreadsConnected(long threadsConnected) { + this.threadsConnected = threadsConnected; + // timeout in 3 minutes + this.threadConnectedTimeout = System.currentTimeMillis() + 3 * 60 * 1000; + } + public void forceThreadsConnected(long threadsConnected, long threadConnectedTimeout) { this.threadsConnected = threadsConnected; this.threadConnectedTimeout = threadConnectedTimeout; diff --git a/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java b/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java index 37889691c..be6a31d29 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java @@ -232,6 +232,16 @@ public XAConnection getXAConnection(String username, String password) throws SQL return new MariaDbPoolConnection(Driver.connect(conf)); } + /** + * Returns the URL for this datasource + * + * @return the URL for this datasource + */ + public String getUrl() { + if (conf == null) return url; + return conf.initialUrl(); + } + /** * Sets the URL for this datasource * @@ -247,16 +257,6 @@ public void setUrl(String url) throws SQLException { } } - /** - * Returns the URL for this datasource - * - * @return the URL for this datasource - */ - public String getUrl() { - if (conf == null) return url; - return conf.initialUrl(); - } - /** * get User * diff --git a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java index 2ae12ad32..3a3cb6d9d 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java @@ -35,6 +35,21 @@ public MariaDbPoolConnection(Connection connection) { connectionEventListeners = new CopyOnWriteArrayList<>(); } + /** + * Create XID string + * + * @param xid xid value + * @return XID string + */ + public static String xidToString(Xid xid) { + return "0x" + + StringUtils.byteArrayToHexString(xid.getGlobalTransactionId()) + + ",0x" + + StringUtils.byteArrayToHexString(xid.getBranchQualifier()) + + ",0x" + + Integer.toHexString(xid.getFormatId()); + } + @Override public Connection getConnection() { return connection; @@ -120,21 +135,6 @@ public void close() throws SQLException { connection.close(); } - /** - * Create XID string - * - * @param xid xid value - * @return XID string - */ - public static String xidToString(Xid xid) { - return "0x" - + StringUtils.byteArrayToHexString(xid.getGlobalTransactionId()) - + ",0x" - + StringUtils.byteArrayToHexString(xid.getBranchQualifier()) - + ",0x" - + Integer.toHexString(xid.getFormatId()); - } - @Override public XAResource getXAResource() { return new MariaDbXAResource(); diff --git a/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java b/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java index d04aedd74..d9d37f442 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java @@ -227,6 +227,16 @@ public XAConnection getXAConnection(String username, String password) throws SQL return pool.getPoolConnection(username, password); } + /** + * Returns the URL for this datasource + * + * @return the URL for this datasource + */ + public String getUrl() { + if (conf == null) return url; + return conf.initialUrl(); + } + /** * Sets the URL for this datasource * @@ -242,16 +252,6 @@ public void setUrl(String url) throws SQLException { } } - /** - * Returns the URL for this datasource - * - * @return the URL for this datasource - */ - public String getUrl() { - if (conf == null) return url; - return conf.initialUrl(); - } - /** * return user * diff --git a/src/main/java/org/mariadb/jdbc/Statement.java b/src/main/java/org/mariadb/jdbc/Statement.java index 85a761439..48ae63e05 100644 --- a/src/main/java/org/mariadb/jdbc/Statement.java +++ b/src/main/java/org/mariadb/jdbc/Statement.java @@ -27,7 +27,7 @@ /** Statement implementation */ public class Statement implements java.sql.Statement { private static final Pattern identifierPattern = - Pattern.compile("[0-9a-zA-Z\\$_\\u0080-\\uFFFF]*", Pattern.UNICODE_CASE | Pattern.CANON_EQ); + Pattern.compile("[0-9a-zA-Z$_\\u0080-\\uFFFF]*", Pattern.UNICODE_CASE | Pattern.CANON_EQ); private static final Pattern escapePattern = Pattern.compile("[\u0000'\"\b\n\r\t\u001A\\\\]"); private static final Map mapper = new HashMap<>(); @@ -43,8 +43,6 @@ public class Statement implements java.sql.Statement { mapper.put("\\", "\\\\"); } - private List batchQueries; - /** result-set type */ protected final int resultSetType; /** concurrency */ @@ -69,15 +67,21 @@ public class Statement implements java.sql.Statement { protected boolean closeOnCompletion; /** closed flag */ protected boolean closed; + /** escape processing */ protected boolean escape; + /** last execution results */ protected List results; + /** current results */ protected Completion currResult; + /** streaming load data infile data */ protected InputStream localInfileInputStream; + private List batchQueries; + /** * Constructor * @@ -731,8 +735,8 @@ public int[] executeBatch() throws SQLException { boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES); if (possibleLoadLocal) { possibleLoadLocal = false; - for (int i = 0; i < batchQueries.size(); i++) { - String sql = batchQueries.get(i).toUpperCase(Locale.ROOT); + for (String batchQuery : batchQueries) { + String sql = batchQuery.toUpperCase(Locale.ROOT); if (sql.contains(" LOCAL ") && sql.contains("LOAD") && sql.contains(" INFILE")) { possibleLoadLocal = true; break; @@ -1484,13 +1488,14 @@ public long[] executeLargeBatch() throws SQLException { // ensure pipelining is possible (no LOAD DATA/XML INFILE commands) boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES); if (possibleLoadLocal) { - for (int i = 0; i < batchQueries.size(); i++) { - String sql = batchQueries.get(i).toUpperCase(Locale.ROOT); + possibleLoadLocal = false; + for (String batchQuery : batchQueries) { + String sql = batchQuery.toUpperCase(Locale.ROOT); if (sql.contains(" LOCAL ") && sql.contains("LOAD") && sql.contains(" INFILE")) { + possibleLoadLocal = true; break; } } - possibleLoadLocal = false; } List res = @@ -1578,12 +1583,11 @@ public List executeInternalBatchStandard() throws SQLException { * * @param val string value to enquote * @return enquoted string value - * @throws SQLException -not possible- */ @Override - public String enquoteLiteral(String val) throws SQLException { + public String enquoteLiteral(String val) { Matcher matcher = escapePattern.matcher(val); - StringBuffer escapedVal = new StringBuffer("'"); + StringBuilder escapedVal = new StringBuilder("'"); while (matcher.find()) { matcher.appendReplacement(escapedVal, mapper.get(matcher.group())); @@ -1626,10 +1630,9 @@ public String enquoteIdentifier(String identifier, boolean alwaysQuote) throws S * @param identifier identifier * @return true if identifier doesn't have to be quoted * @see mariadb identifier name - * @throws SQLException exception */ @Override - public boolean isSimpleIdentifier(String identifier) throws SQLException { + public boolean isSimpleIdentifier(String identifier) { return identifier != null && !identifier.isEmpty() && identifierPattern.matcher(identifier).matches(); @@ -1640,10 +1643,9 @@ public boolean isSimpleIdentifier(String identifier) throws SQLException { * * @param val value to enquote * @return enquoted String value - * @throws SQLException - not possible - */ @Override - public String enquoteNCharLiteral(String val) throws SQLException { + public String enquoteNCharLiteral(String val) { return "N'" + val.replace("'", "''") + "'"; } } diff --git a/src/main/java/org/mariadb/jdbc/TransactionIsolation.java b/src/main/java/org/mariadb/jdbc/TransactionIsolation.java index a910ecbd8..51405e1b4 100644 --- a/src/main/java/org/mariadb/jdbc/TransactionIsolation.java +++ b/src/main/java/org/mariadb/jdbc/TransactionIsolation.java @@ -45,24 +45,6 @@ public enum TransactionIsolation { this.level = level; } - /** - * Get transaction isolation command - * - * @return transaction isolation command - */ - public String getValue() { - return value; - } - - /** - * Get transaction isolation level - * - * @return transaction isolation level - */ - public int getLevel() { - return level; - } - /** * Get TransactionIsolation from value * @@ -81,4 +63,22 @@ public static TransactionIsolation from(String value) { throw new IllegalArgumentException( String.format("Wrong argument value '%s' for TransactionIsolation", value)); } + + /** + * Get transaction isolation command + * + * @return transaction isolation command + */ + public String getValue() { + return value; + } + + /** + * Get transaction isolation level + * + * @return transaction isolation level + */ + public int getLevel() { + return level; + } } diff --git a/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java b/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java index d95225f72..0809505ae 100644 --- a/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java +++ b/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java @@ -18,6 +18,128 @@ public interface ColumnDecoder extends Column { + /** + * Decode Column from mysql packet + * + * @param buf packet + * @param extendedInfo is extended datatype information capability enable + * @return column + */ + static ColumnDecoder decode(ReadableByteBuf buf, boolean extendedInfo) { + // skip first strings + int[] stringPos = new int[5]; + stringPos[0] = buf.skipIdentifier(); // schema pos + stringPos[1] = buf.skipIdentifier(); // table alias pos + stringPos[2] = buf.skipIdentifier(); // table pos + stringPos[3] = buf.skipIdentifier(); // column alias pos + stringPos[4] = buf.skipIdentifier(); // column pos + buf.skipIdentifier(); + + String extTypeName = null; + String extTypeFormat = null; + if (extendedInfo) { + // fast skipping extended info (usually not set) + if (buf.readByte() != 0) { + // revert position, because has extended info. + buf.pos(buf.pos() - 1); + + ReadableByteBuf subPacket = buf.readLengthBuffer(); + while (subPacket.readableBytes() > 0) { + switch (subPacket.readByte()) { + case 0: + extTypeName = subPacket.readAscii(subPacket.readLength()); + break; + case 1: + extTypeFormat = subPacket.readAscii(subPacket.readLength()); + break; + default: // skip data + subPacket.skip(subPacket.readLength()); + break; + } + } + } + } + + buf.skip(); // skip length always 0x0c + short charset = buf.readShort(); + int length = buf.readInt(); + DataType dataType = DataType.of(buf.readUnsignedByte()); + int flags = buf.readUnsignedShort(); + byte decimals = buf.readByte(); + DataType.ColumnConstructor constructor = + (extTypeName != null && extTypeName.equals("uuid")) + ? UuidColumn::new + : (flags & ColumnFlags.UNSIGNED) == 0 + ? dataType.getColumnConstructor() + : dataType.getUnsignedColumnConstructor(); + return constructor.create( + buf, charset, length, dataType, decimals, flags, stringPos, extTypeName, extTypeFormat); + } + + /** + * Create fake MySQL column definition packet with indicated datatype + * + * @param name column name + * @param type data type + * @param flags column flags + * @return Column + */ + static ColumnDecoder create(String name, DataType type, int flags) { + byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); + byte[] arr = new byte[9 + 2 * nameBytes.length]; + arr[0] = 3; + arr[1] = 'D'; + arr[2] = 'E'; + arr[3] = 'F'; + + int[] stringPos = new int[5]; + stringPos[0] = 4; // schema pos + stringPos[1] = 5; // table alias pos + stringPos[2] = 6; // table pos + + // lenenc_str name + // lenenc_str org_name + int pos = 7; + for (int i = 0; i < 2; i++) { + stringPos[i + 3] = pos; + arr[pos++] = (byte) nameBytes.length; + System.arraycopy(nameBytes, 0, arr, pos, nameBytes.length); + pos += nameBytes.length; + } + int len; + + /* Sensible predefined length - since we're dealing with I_S here, most char fields are 64 char long */ + switch (type) { + case VARCHAR: + case VARSTRING: + len = 64 * 3; /* 3 bytes per UTF8 char */ + break; + case SMALLINT: + len = 5; + break; + case NULL: + len = 0; + break; + default: + len = 1; + break; + } + DataType.ColumnConstructor constructor = + (flags & ColumnFlags.UNSIGNED) == 0 + ? type.getColumnConstructor() + : type.getUnsignedColumnConstructor(); + return constructor.create( + new StandardReadableByteBuf(arr, arr.length), + 33, + len, + type, + (byte) 0, + flags, + stringPos, + null, + null); + } + /** * Returns default class name depending on server column datatype * @@ -192,6 +314,7 @@ Timestamp decodeTimestampText(final ReadableByteBuf buf, final MutableInt length */ Timestamp decodeTimestampBinary(final ReadableByteBuf buf, final MutableInt length, Calendar cal) throws SQLDataException; + /** * Return boolean text encoded value * @@ -213,6 +336,7 @@ boolean decodeBooleanText(final ReadableByteBuf buf, final MutableInt length) */ boolean decodeBooleanBinary(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse short text encoded value * @@ -222,6 +346,7 @@ boolean decodeBooleanBinary(final ReadableByteBuf buf, final MutableInt length) * @throws SQLDataException if any decoding error occurs */ short decodeShortText(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse short binary encoded value * @@ -232,6 +357,7 @@ boolean decodeBooleanBinary(final ReadableByteBuf buf, final MutableInt length) */ short decodeShortBinary(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse int text encoded value * @@ -261,6 +387,7 @@ short decodeShortBinary(final ReadableByteBuf buf, final MutableInt length) * @throws SQLDataException if any decoding error occurs */ long decodeLongText(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse long binary encoded value * @@ -313,126 +440,4 @@ float decodeFloatBinary(final ReadableByteBuf buf, final MutableInt length) */ double decodeDoubleBinary(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; - - /** - * Decode Column from mysql packet - * - * @param buf packet - * @param extendedInfo is extended datatype information capability enable - * @return column - */ - static ColumnDecoder decode(ReadableByteBuf buf, boolean extendedInfo) { - // skip first strings - int[] stringPos = new int[5]; - stringPos[0] = buf.skipIdentifier(); // schema pos - stringPos[1] = buf.skipIdentifier(); // table alias pos - stringPos[2] = buf.skipIdentifier(); // table pos - stringPos[3] = buf.skipIdentifier(); // column alias pos - stringPos[4] = buf.skipIdentifier(); // column pos - buf.skipIdentifier(); - - String extTypeName = null; - String extTypeFormat = null; - if (extendedInfo) { - // fast skipping extended info (usually not set) - if (buf.readByte() != 0) { - // revert position, because has extended info. - buf.pos(buf.pos() - 1); - - ReadableByteBuf subPacket = buf.readLengthBuffer(); - while (subPacket.readableBytes() > 0) { - switch (subPacket.readByte()) { - case 0: - extTypeName = subPacket.readAscii(subPacket.readLength()); - break; - case 1: - extTypeFormat = subPacket.readAscii(subPacket.readLength()); - break; - default: // skip data - subPacket.skip(subPacket.readLength()); - break; - } - } - } - } - - buf.skip(); // skip length always 0x0c - short charset = buf.readShort(); - int length = buf.readInt(); - DataType dataType = DataType.of(buf.readUnsignedByte()); - int flags = buf.readUnsignedShort(); - byte decimals = buf.readByte(); - DataType.ColumnConstructor constructor = - (extTypeName != null && extTypeName.equals("uuid")) - ? UuidColumn::new - : (flags & ColumnFlags.UNSIGNED) == 0 - ? dataType.getColumnConstructor() - : dataType.getUnsignedColumnConstructor(); - return constructor.create( - buf, charset, length, dataType, decimals, flags, stringPos, extTypeName, extTypeFormat); - } - - /** - * Create fake MySQL column definition packet with indicated datatype - * - * @param name column name - * @param type data type - * @param flags column flags - * @return Column - */ - static ColumnDecoder create(String name, DataType type, int flags) { - byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); - byte[] arr = new byte[9 + 2 * nameBytes.length]; - arr[0] = 3; - arr[1] = 'D'; - arr[2] = 'E'; - arr[3] = 'F'; - - int[] stringPos = new int[5]; - stringPos[0] = 4; // schema pos - stringPos[1] = 5; // table alias pos - stringPos[2] = 6; // table pos - - // lenenc_str name - // lenenc_str org_name - int pos = 7; - for (int i = 0; i < 2; i++) { - stringPos[i + 3] = pos; - arr[pos++] = (byte) nameBytes.length; - System.arraycopy(nameBytes, 0, arr, pos, nameBytes.length); - pos += nameBytes.length; - } - int len; - - /* Sensible predefined length - since we're dealing with I_S here, most char fields are 64 char long */ - switch (type) { - case VARCHAR: - case VARSTRING: - len = 64 * 3; /* 3 bytes per UTF8 char */ - break; - case SMALLINT: - len = 5; - break; - case NULL: - len = 0; - break; - default: - len = 1; - break; - } - DataType.ColumnConstructor constructor = - (flags & ColumnFlags.UNSIGNED) == 0 - ? type.getColumnConstructor() - : type.getUnsignedColumnConstructor(); - return constructor.create( - new StandardReadableByteBuf(arr, arr.length), - 33, - len, - type, - (byte) 0, - flags, - stringPos, - null, - null); - } } diff --git a/src/main/java/org/mariadb/jdbc/client/Context.java b/src/main/java/org/mariadb/jdbc/client/Context.java index 500e79058..b0283d041 100644 --- a/src/main/java/org/mariadb/jdbc/client/Context.java +++ b/src/main/java/org/mariadb/jdbc/client/Context.java @@ -16,6 +16,13 @@ public interface Context { */ long getThreadId(); + /** + * Indicate server connection Id (not truncated) + * + * @param connectionId connection id + */ + void setThreadId(long connectionId); + /** * Get connection initial seed * @@ -171,20 +178,6 @@ public interface Context { */ void addStateFlag(int state); - /** - * Indicate server charset change - * - * @param charset server charset - */ - void setCharset(String charset); - - /** - * Indicate server connection Id (not truncated) - * - * @param connectionId connection id - */ - void setThreadId(long connectionId); - /** Indicate the number of connection on this server */ void setTreadsConnected(long threadsConnected); @@ -194,4 +187,11 @@ public interface Context { * @return current charset */ String getCharset(); + + /** + * Indicate server charset change + * + * @param charset server charset + */ + void setCharset(String charset); } diff --git a/src/main/java/org/mariadb/jdbc/client/DataType.java b/src/main/java/org/mariadb/jdbc/client/DataType.java index 8a3ca8c5d..8ee64d034 100644 --- a/src/main/java/org/mariadb/jdbc/client/DataType.java +++ b/src/main/java/org/mariadb/jdbc/client/DataType.java @@ -58,14 +58,14 @@ public enum DataType { this.unsignedColumnConstructor = unsignedColumnConstructor; } - public int get() { - return mariadbType; - } - public static DataType of(int typeValue) { return typeMap[typeValue]; } + public int get() { + return mariadbType; + } + public ColumnConstructor getColumnConstructor() { return columnConstructor; } diff --git a/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java b/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java index e811b38ab..be907b7dc 100644 --- a/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java +++ b/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java @@ -90,19 +90,20 @@ public interface ReadableByteBuf { short getUnsignedByte(); /** - * Read encoded length value that cannot be null see - * https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers + * Read encoded length value that cannot be null * + * @see length + * encoded integer * @return encoded length */ long readLongLengthEncodedNotNull(); /** - * Read encoded length value that cannot be null see - * https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers - * - *

this is readLongLengthEncodedNotNull limited to 32 bits + * Read encoded length value that cannot be null * + * @see length + * encoded integer + *

this is readLongLengthEncodedNotNull limited to 32 bits * @return encoded length */ int readIntLengthEncodedNotNull(); @@ -129,10 +130,12 @@ public interface ReadableByteBuf { * @return long value */ long atoull(int length); + /** - * Read encoded length value see - * https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers + * Read encoded length value * + * @see length + * encoded integer * @return encoded length */ Integer readLength(); diff --git a/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java b/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java index d5e99a81c..26a96dbfb 100644 --- a/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java +++ b/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java @@ -18,7 +18,6 @@ /** Context (current connection state) of a connection */ public class BaseContext implements Context { - private long threadId; private final long serverCapabilities; private final long clientCapabilities; private final byte[] seed; @@ -29,11 +28,17 @@ public class BaseContext implements Context { private final Configuration conf; private final ExceptionFactory exceptionFactory; - private String charset; + /** LRU prepare cache object */ + private final PrepareCache prepareCache; + + private final HostAddress hostAddress; /** Server status context */ protected int serverStatus; + private long threadId; + private String charset; + /** Server current database */ private String database; @@ -43,14 +48,9 @@ public class BaseContext implements Context { /** Server current warning count */ private int warning; - /** LRU prepare cache object */ - private final PrepareCache prepareCache; - /** Connection state use flag */ private int stateFlag = 0; - private final HostAddress hostAddress; - /** * Constructor of connection context * @@ -88,6 +88,10 @@ public long getThreadId() { return threadId; } + public void setThreadId(long connectionId) { + threadId = connectionId; + } + public byte[] getSeed() { return seed; } @@ -180,14 +184,6 @@ public void addStateFlag(int state) { stateFlag |= state; } - public void setCharset(String charset) { - this.charset = charset; - } - - public void setThreadId(long connectionId) { - threadId = connectionId; - } - public void setTreadsConnected(long threadsConnected) { if (hostAddress != null) hostAddress.setThreadsConnected(threadsConnected); } @@ -195,4 +191,8 @@ public void setTreadsConnected(long threadsConnected) { public String getCharset() { return charset; } + + public void setCharset(String charset) { + this.charset = charset; + } } diff --git a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java index 77802c5b9..2ee4405e9 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java @@ -36,23 +36,23 @@ * supported proxy class. */ public class MultiPrimaryClient implements Client { - private static final Logger logger = Loggers.getLogger(MultiPrimaryClient.class); - /** temporary blacklisted hosts */ protected static final ConcurrentMap denyList = new ConcurrentHashMap<>(); + private static final Logger logger = Loggers.getLogger(MultiPrimaryClient.class); + /** denied timeout */ protected final long deniedListTimeout; /** configuration */ protected final Configuration conf; - /** is connections explicitly closed */ - protected boolean closed = false; - /** thread locker */ protected final ReentrantLock lock; + /** is connections explicitly closed */ + protected boolean closed = false; + /** current client */ protected Client currentClient; diff --git a/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java b/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java index 4e77e2588..66db2b250 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java @@ -16,8 +16,10 @@ public final class PrepareCache extends LinkedHashMap mapper = null; - /** is fully loaded */ protected boolean loaded; @@ -95,6 +89,11 @@ public abstract class Result implements ResultSet, Completion { /** row number limit */ protected long maxRows; + private final MutableInt fieldLength = new MutableInt(0); + private boolean forceAlias; + private byte[] nullBitmap; + private Map mapper = null; + /** * Constructor for server's data * @@ -852,6 +851,16 @@ public boolean isBeforeFirst() throws SQLException { @Override public abstract int getRow() throws SQLException; + /** + * set row decoder to current row data + * + * @param row row + */ + public void setRow(byte[] row) { + rowBuf.buf(row, row.length, 0); + fieldIndex.set(-1); + } + @Override public abstract boolean absolute(int row) throws SQLException; @@ -1680,16 +1689,6 @@ protected void setNullRowBuf() { rowBuf.buf(null, 0, 0); } - /** - * set row decoder to current row data - * - * @param row row - */ - public void setRow(byte[] row) { - rowBuf.buf(row, row.length, 0); - fieldIndex.set(-1); - } - public int findColumn(String label) throws SQLException { if (label == null) throw new SQLException("null is not a valid label value"); if (mapper == null) { diff --git a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java index b39e6fc7d..be8044304 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java +++ b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java @@ -120,6 +120,7 @@ boolean decodeBoolean( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to Date. * @@ -138,6 +139,7 @@ Date decodeDate( MutableInt fieldLength, Calendar cal) throws SQLException; + /** * Decode data according to Time. * @@ -156,6 +158,7 @@ Time decodeTime( MutableInt fieldLength, Calendar cal) throws SQLException; + /** * Decode data according to Timestamp. * @@ -174,6 +177,7 @@ Timestamp decodeTimestamp( MutableInt fieldLength, Calendar cal) throws SQLException; + /** * Decode data according to short. * @@ -190,6 +194,7 @@ short decodeShort( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to int. * @@ -206,6 +211,7 @@ int decodeInt( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to String. * @@ -222,6 +228,7 @@ String decodeString( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to long. * @@ -238,6 +245,7 @@ long decodeLong( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to float. * @@ -254,6 +262,7 @@ float decodeFloat( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to double. * diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java index e7234e2de..fda769f83 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java @@ -20,18 +20,15 @@ /** Packet reader */ public class PacketReader implements Reader { - private StandardReadableByteBuf readBuf = new StandardReadableByteBuf(null, 0); - private static final int REUSABLE_BUFFER_LENGTH = 1024; private static final int MAX_PACKET_SIZE = 0xffffff; private static final Logger logger = Loggers.getLogger(PacketReader.class); - private final byte[] header = new byte[4]; private final byte[] reusableArray = new byte[REUSABLE_BUFFER_LENGTH]; private final InputStream inputStream; private final int maxQuerySizeToLog; - private final MutableByte sequence; + private final StandardReadableByteBuf readBuf = new StandardReadableByteBuf(null, 0); private String serverThreadLog = ""; /** diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java index 9807bb937..f685b91bc 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java @@ -31,24 +31,29 @@ public class PacketWriter implements Writer { private static final int MEDIUM_BUFFER_SIZE = 128 * 1024; private static final int LARGE_BUFFER_SIZE = 1024 * 1024; private static final int MAX_PACKET_LENGTH = 0x00ffffff + 4; + + /** packet sequence */ + protected final MutableByte sequence; + + /** compressed packet sequence */ + protected final MutableByte compressSequence; + private final int maxQuerySizeToLog; private final OutputStream out; - private int maxPacketLength = MAX_PACKET_LENGTH; - private Integer maxAllowedPacket; - private long cmdLength; - private boolean permitTrace = true; - private String serverThreadLog = ""; - private int mark = -1; - private boolean bufContainDataAfterMark = false; + private final int maxPacketLength = MAX_PACKET_LENGTH; + private final Integer maxAllowedPacket; /** internal buffer */ protected byte[] buf; + /** buffer position */ protected int pos = 4; - /** packet sequence */ - protected final MutableByte sequence; - /** compressed packet sequence */ - protected final MutableByte compressSequence; + + private long cmdLength; + private boolean permitTrace = true; + private String serverThreadLog = ""; + private int mark = -1; + private boolean bufContainDataAfterMark = false; /** * Common feature to write data into socket, creating MariaDB Packet. diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java index 5bac1f005..90ef48da1 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java @@ -57,8 +57,9 @@ public UnixDomainSocket(String path) throws IOException { /** * creates an endpoint for communication and returns a file descriptor that refers to that - * endpoint. see https://man7.org/linux/man-pages/man2/socket.2.html + * endpoint. * + * @see Socket * @param domain domain * @param type type * @param protocol protocol @@ -85,7 +86,8 @@ public static native int connect(int sockfd, SockAddr sockaddr, int addrlen) * @param fd file descriptor * @param buffer buffer * @param count length - * @param flags flag. see https://man7.org/linux/man-pages/man2/recvmsg.2.html + * @param flags flag. @see flags * @return zero on success. -1 on error * @throws LastErrorException if error occurs */ @@ -98,7 +100,8 @@ public static native int recv(int fd, byte[] buffer, int count, int flags) * @param fd file descriptor * @param buffer buffer * @param count length - * @param flags flag. see https://man7.org/linux/man-pages/man2/sendmsg.2.html + * @param flags flag. @see flags * @return zero on success. -1 on error * @throws LastErrorException if error occurs */ @@ -158,6 +161,7 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { try { close(); } catch (IOException e) { + // eat } throw new IOException("native connect() failed : " + formatError(lee)); @@ -200,8 +204,7 @@ public void shutdownOutput() { /** Socket address */ public static class SockAddr extends Structure { - /** socket family */ - public short sun_family = AF_UNIX; + /** pathname */ public byte[] sun_path; diff --git a/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java b/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java index e97338ef3..311d3f3fd 100644 --- a/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java +++ b/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java @@ -6,6 +6,8 @@ /** Mutable int */ public class MutableInt { + private int value; + public MutableInt() { this.value = -1; } @@ -14,8 +16,6 @@ public MutableInt(int value) { this.value = value; } - private int value; - /** * Set new sequence value * diff --git a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java index c85b37948..9401ccfb1 100644 --- a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java +++ b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java @@ -358,6 +358,7 @@ public SQLException create(String message, String sqlState) { public SQLException create(String message, String sqlState, Exception cause) { return createException(message, sqlState, -1, cause); } + /** * Creation of an exception * diff --git a/src/main/java/org/mariadb/jdbc/export/HaMode.java b/src/main/java/org/mariadb/jdbc/export/HaMode.java index 95d5ee26e..2fa979724 100644 --- a/src/main/java/org/mariadb/jdbc/export/HaMode.java +++ b/src/main/java/org/mariadb/jdbc/export/HaMode.java @@ -64,12 +64,6 @@ public Optional getAvailableHost( this.value = value; } - /** For testing purpose only */ - public void resetLast() { - lastRoundRobinPrimaryHost = null; - lastRoundRobinSecondaryHost = null; - } - /** * Get HAMode from values or aliases * @@ -201,6 +195,12 @@ public static Optional getAvailableRoundRobinHost( return Optional.empty(); } + /** For testing purpose only */ + public void resetLast() { + lastRoundRobinPrimaryHost = null; + lastRoundRobinSecondaryHost = null; + } + /** * List of hosts without blacklist entries, ordered according to HA mode * diff --git a/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java b/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java index 23e0da7b4..4c7691c3b 100644 --- a/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java +++ b/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java @@ -13,6 +13,7 @@ public class MaxAllowedPacketException extends IOException { private static final long serialVersionUID = 5669184960442818475L; + /** is connection in wrong state */ private final boolean mustReconnect; diff --git a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java index 979832937..1bd9022d6 100644 --- a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java @@ -29,6 +29,45 @@ public interface ClientMessage { + /** + * Check that file requested correspond to request. + * + * @param sql current command sql + * @param parameters current command parameter + * @param fileName file path request + * @param context current connection context + * @return true if file name correspond to demand and query is a load local infile + */ + static boolean validateLocalFileName( + String sql, Parameters parameters, String fileName, Context context) { + String reg = + "^(\\s*/\\*([^*]|\\*[^/])*\\*/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+'" + + Pattern.quote(fileName.replace("\\", "\\\\")) + + "'"; + + Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); + if (pattern.matcher(sql).find()) { + return true; + } + + if (parameters != null) { + pattern = + Pattern.compile( + "^(\\s*/\\*([^*]|\\*[^/])*\\*/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+\\?", + Pattern.CASE_INSENSITIVE); + if (pattern.matcher(sql).find() && parameters.size() > 0) { + String paramString = parameters.get(0).bestEffortStringValue(context); + if (paramString != null) { + return paramString + .toLowerCase() + .equals("'" + fileName.replace("\\", "\\\\").toLowerCase() + "'"); + } + return true; + } + } + return false; + } + /** * Encode client message to socket. * @@ -206,7 +245,7 @@ default Completion readPacket( ColumnDecoder[] ci; boolean canSkipMeta = context.canSkipMeta() && this.canSkipMeta(); - boolean skipMeta = canSkipMeta ? buf.readByte() == 0 : false; + boolean skipMeta = canSkipMeta && buf.readByte() == 0; if (canSkipMeta && skipMeta) { ci = ((BasePreparedStatement) stmt).getMeta(); } else { @@ -291,43 +330,4 @@ default InputStream getLocalInfileInputStream() { default boolean validateLocalFileName(String fileName, Context context) { return false; } - - /** - * Check that file requested correspond to request. - * - * @param sql current command sql - * @param parameters current command parameter - * @param fileName file path request - * @param context current connection context - * @return true if file name correspond to demand and query is a load local infile - */ - static boolean validateLocalFileName( - String sql, Parameters parameters, String fileName, Context context) { - String reg = - "^(\\s*\\/\\*([^\\*]|\\*[^\\/])*\\*\\/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+'" - + Pattern.quote(fileName.replace("\\", "\\\\")) - + "'"; - - Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); - if (pattern.matcher(sql).find()) { - return true; - } - - if (parameters != null) { - pattern = - Pattern.compile( - "^(\\s*\\/\\*([^\\*]|\\*[^\\/])*\\*\\/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+\\?", - Pattern.CASE_INSENSITIVE); - if (pattern.matcher(sql).find() && parameters.size() > 0) { - String paramString = parameters.get(0).bestEffortStringValue(context); - if (paramString != null) { - return paramString - .toLowerCase() - .equals("'" + fileName.replace("\\", "\\\\").toLowerCase() + "'"); - } - return true; - } - } - return false; - } } diff --git a/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java index f5b70e984..22f1ec731 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java @@ -19,13 +19,14 @@ import org.mariadb.jdbc.message.server.PrepareResultPacket; /** - * batch execution. This relies on COM_STMT_BULK_EXECUTE see - * https://mariadb.com/kb/en/com_stmt_bulk_execute/ + * batch execution. This relies on COM_STMT_BULK_EXECUTE + * + * @see documentation */ public final class BulkExecutePacket implements RedoableWithPrepareClientMessage { - private List batchParameterList; private final String command; private final ServerPreparedStatement prep; + private List batchParameterList; private Prepare prepareResult; /** diff --git a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java index 4f8e9b9eb..4a1334725 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java @@ -18,15 +18,16 @@ import org.mariadb.jdbc.plugin.codec.ByteArrayCodec; /** - * Execute command (COM_STMT_EXECUTE) See https://mariadb.com/kb/en/com_stmt_execute/ for - * documentation + * Execute command (COM_STMT_EXECUTE) + * + * @see Execute documentation */ public final class ExecutePacket implements RedoableWithPrepareClientMessage { - private Parameters parameters; private final String command; private final ServerPreparedStatement prep; + private final InputStream localInfileInputStream; private Prepare prepareResult; - private InputStream localInfileInputStream; + private Parameters parameters; /** * Constructor diff --git a/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java index 8a5023733..76ac3d3f0 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java @@ -28,14 +28,16 @@ /** * Send a client COM_STMT_PREPARE + COM_STMT_EXECUTE packets see - * https://mariadb.com/kb/en/com_stmt_prepare/ + * + * @see Prepare packet */ public final class PrepareExecutePacket implements RedoableWithPrepareClientMessage { private final String sql; - private Parameters parameters; private final ServerPreparedStatement prep; + private final InputStream localInfileInputStream; private PrepareResultPacket prepareResult; - private InputStream localInfileInputStream; + private Parameters parameters; + /** * Construct prepare packet * diff --git a/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java b/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java index 3beecb895..94f2485e0 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java @@ -9,8 +9,10 @@ import org.mariadb.jdbc.message.ServerMessage; /** - * Authentication switch packet. See - * https://mariadb.com/kb/en/connection/#authentication-switch-request + * Authentication switch packet. + * + * @see Authentication + * switch packet */ public class AuthSwitchPacket implements ServerMessage { @@ -43,6 +45,16 @@ public static AuthSwitchPacket decode(ReadableByteBuf buf) { return new AuthSwitchPacket(plugin, seed); } + /** + * Get truncated seed (seed without ending 0x00 byte) + * + * @param seed connection seed + * @return truncated seed + */ + public static byte[] getTruncatedSeed(byte[] seed) { + return (seed.length > 0) ? Arrays.copyOfRange(seed, 0, seed.length - 1) : new byte[0]; + } + /** * Get authentication switch plugin information * @@ -60,14 +72,4 @@ public String getPlugin() { public byte[] getSeed() { return seed; } - - /** - * Get truncated seed (seed without ending 0x00 byte) - * - * @param seed connection seed - * @return truncated seed - */ - public static byte[] getTruncatedSeed(byte[] seed) { - return (seed.length > 0) ? Arrays.copyOfRange(seed, 0, seed.length - 1) : new byte[0]; - } } diff --git a/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java b/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java index 9ca8ade63..c8e0142c8 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java @@ -15,23 +15,37 @@ /** Column metadata definition */ public class ColumnDefinitionPacket implements Column, ServerMessage { - private final ReadableByteBuf buf; /** charset */ protected final int charset; + /** column maximum length */ protected final long columnLength; - /** data type see https://mariadb.com/kb/en/result-set-packets/#field-types */ + + /** + * data type @see Field + * type + */ protected final DataType dataType; + /** number of decimal */ protected final byte decimals; - /** flags see https://mariadb.com/kb/en/result-set-packets/#field-details-flag */ - private final int flags; - /** string offset position in buffer */ - private final int[] stringPos; + /** extended type name */ protected final String extTypeName; + /** extended type format */ protected final String extTypeFormat; + + private final ReadableByteBuf buf; + + /** + * @see flags + */ + private final int flags; + + /** string offset position in buffer */ + private final int[] stringPos; + /** configuration: use alias as name */ private boolean useAliasAsName; diff --git a/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java b/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java index 982159f12..ae1f3b1df 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java @@ -15,9 +15,15 @@ import org.mariadb.jdbc.util.log.Logger; import org.mariadb.jdbc.util.log.Loggers; -/** Prepare result packet See https://mariadb.com/kb/en/com_stmt_prepare/#COM_STMT_PREPARE_OK */ +/** + * Prepare result packet + * + * @see Prepare result + * packet * + */ public class PrepareResultPacket implements Completion, Prepare { static final ColumnDecoder CONSTANT_PARAMETER; + private static final Logger logger = Loggers.getLogger(PrepareResultPacket.class); static { byte[] bytes = @@ -51,13 +57,13 @@ public class PrepareResultPacket implements Completion, Prepare { ColumnDecoder.decode(new StandardReadableByteBuf(bytes, bytes.length), true); } - private static final Logger logger = Loggers.getLogger(PrepareResultPacket.class); private final ColumnDecoder[] parameters; - private ColumnDecoder[] columns; /** prepare statement id */ protected int statementId; + private ColumnDecoder[] columns; + /** * Prepare packet constructor (parsing) * diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java index 0dbeeaeec..91159a2c5 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java @@ -72,6 +72,83 @@ public static byte[] sha256encryptPassword(final CharSequence password, final by } } + /** + * Read public Key from file. + * + * @param serverRsaPublicKeyFile RSA public key file + * @return public key + * @throws SQLException if having an error reading file or file content is not a public key. + */ + public static PublicKey readPublicKeyFromFile(String serverRsaPublicKeyFile) throws SQLException { + byte[] keyBytes; + try { + keyBytes = Files.readAllBytes(Paths.get(serverRsaPublicKeyFile)); + } catch (IOException ex) { + throw new SQLException( + "Could not read server RSA public key from file : " + + "serverRsaPublicKeyFile=" + + serverRsaPublicKeyFile, + "S1009", + ex); + } + return generatePublicKey(keyBytes); + } + + /** + * Read public pem key from String. + * + * @param publicKeyBytes public key bytes value + * @return public key + * @throws SQLException if key cannot be parsed + */ + public static PublicKey generatePublicKey(byte[] publicKeyBytes) throws SQLException { + try { + String publicKey = + new String(publicKeyBytes, StandardCharsets.US_ASCII) + .replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)", ""); + + byte[] keyBytes = Base64.getMimeDecoder().decode(publicKey); + X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); + KeyFactory kf = KeyFactory.getInstance("RSA"); + return kf.generatePublic(spec); + } catch (Exception ex) { + throw new SQLException("Could read server RSA public key: " + ex.getMessage(), "S1009", ex); + } + } + + /** + * Encode password with seed and public key. + * + * @param publicKey public key + * @param password password + * @param seed seed + * @return encoded password + * @throws SQLException if cannot encode password + */ + public static byte[] encrypt(PublicKey publicKey, String password, byte[] seed) + throws SQLException { + + byte[] correctedSeed = Arrays.copyOfRange(seed, 0, seed.length - 1); + byte[] bytePwd = password.getBytes(StandardCharsets.UTF_8); + + byte[] nullFinishedPwd = Arrays.copyOf(bytePwd, bytePwd.length + 1); + byte[] xorBytes = new byte[nullFinishedPwd.length]; + int seedLength = correctedSeed.length; + + for (int i = 0; i < xorBytes.length; i++) { + xorBytes[i] = (byte) (nullFinishedPwd[i] ^ correctedSeed[i % seedLength]); + } + + try { + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return cipher.doFinal(xorBytes); + } catch (Exception ex) { + throw new SQLException( + "Error encoding password with public key : " + ex.getMessage(), "S1009", ex); + } + } + @Override public String type() { return TYPE; @@ -180,81 +257,4 @@ public ReadableByteBuf process(Writer out, Reader in, Context context) } } } - - /** - * Read public Key from file. - * - * @param serverRsaPublicKeyFile RSA public key file - * @return public key - * @throws SQLException if having an error reading file or file content is not a public key. - */ - public static PublicKey readPublicKeyFromFile(String serverRsaPublicKeyFile) throws SQLException { - byte[] keyBytes; - try { - keyBytes = Files.readAllBytes(Paths.get(serverRsaPublicKeyFile)); - } catch (IOException ex) { - throw new SQLException( - "Could not read server RSA public key from file : " - + "serverRsaPublicKeyFile=" - + serverRsaPublicKeyFile, - "S1009", - ex); - } - return generatePublicKey(keyBytes); - } - - /** - * Read public pem key from String. - * - * @param publicKeyBytes public key bytes value - * @return public key - * @throws SQLException if key cannot be parsed - */ - public static PublicKey generatePublicKey(byte[] publicKeyBytes) throws SQLException { - try { - String publicKey = - new String(publicKeyBytes, StandardCharsets.US_ASCII) - .replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)", ""); - - byte[] keyBytes = Base64.getMimeDecoder().decode(publicKey); - X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance("RSA"); - return kf.generatePublic(spec); - } catch (Exception ex) { - throw new SQLException("Could read server RSA public key: " + ex.getMessage(), "S1009", ex); - } - } - - /** - * Encode password with seed and public key. - * - * @param publicKey public key - * @param password password - * @param seed seed - * @return encoded password - * @throws SQLException if cannot encode password - */ - public static byte[] encrypt(PublicKey publicKey, String password, byte[] seed) - throws SQLException { - - byte[] correctedSeed = Arrays.copyOfRange(seed, 0, seed.length - 1); - byte[] bytePwd = password.getBytes(StandardCharsets.UTF_8); - - byte[] nullFinishedPwd = Arrays.copyOf(bytePwd, bytePwd.length + 1); - byte[] xorBytes = new byte[nullFinishedPwd.length]; - int seedLength = correctedSeed.length; - - for (int i = 0; i < xorBytes.length; i++) { - xorBytes[i] = (byte) (nullFinishedPwd[i] ^ correctedSeed[i % seedLength]); - } - - try { - Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); - cipher.init(Cipher.ENCRYPT_MODE, publicKey); - return cipher.doFinal(xorBytes); - } catch (Exception ex) { - throw new SQLException( - "Error encoding password with public key : " + ex.getMessage(), "S1009", ex); - } - } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java index 2eecde671..b989b39c8 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java @@ -19,8 +19,10 @@ public class Field implements Serializable { private final int b; private final FieldElement q; + /** q-2 */ private final FieldElement qm2; + /** (q-5) / 8 */ private final FieldElement qm5d8; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java index feb9ffa5b..bf64655a0 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java @@ -26,165 +26,24 @@ */ public class GroupElement implements Serializable { private static final long serialVersionUID = 2395879087349587L; - - /** - * Available representations for a group element. - * - *

    - *
  • P2: Projective representation $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$. - *
  • P3: Extended projective representation $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$. - *
  • P3PrecomputedDouble: P3 but with dblPrecmp populated. - *
  • P1P1: Completed representation $((X:Z), (Y:T))$ satisfying $x=X/Z, y=Y/T$. - *
  • PRECOMP: Precomputed representation $(y+x, y-x, 2dxy)$. - *
  • CACHED: Cached representation $(Y+X, Y-X, Z, 2dT)$ - *
- */ - public enum Representation { - /** Projective ($P^2$): $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$ */ - P2, - /** Extended ($P^3$): $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$ */ - P3, - /** Can only be requested. Results in P3 representation but also populates dblPrecmp. */ - P3PrecomputedDouble, - /** Completed ($P \times P$): $((X:Z),(Y:T))$ satisfying $x=X/Z, y=Y/T$ */ - P1P1, - /** Precomputed (Duif): $(y+x,y-x,2dxy)$ */ - PRECOMP, - /** Cached: $(Y+X,Y-X,Z,2dT)$ */ - CACHED - } - - /** - * Creates a new group element in P2 representation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @return The group element in P2 representation. - */ - public static GroupElement p2( - final Curve curve, final FieldElement X, final FieldElement Y, final FieldElement Z) { - return new GroupElement(curve, Representation.P2, X, Y, Z, null); - } - - /** - * Creates a new group element in P3 representation, without pre-computation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @param T The $T$ coordinate. - * @return The group element in P3 representation. - */ - public static GroupElement p3( - final Curve curve, - final FieldElement X, - final FieldElement Y, - final FieldElement Z, - final FieldElement T) { - return p3(curve, X, Y, Z, T, false); - } - - /** - * Creates a new group element in P3 representation, potentially with pre-computation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @param T The $T$ coordinate. - * @param precomputeDoubleOnly If true, populate dblPrecmp, else set to null. - * @return The group element in P3 representation. - */ - public static GroupElement p3( - final Curve curve, - final FieldElement X, - final FieldElement Y, - final FieldElement Z, - final FieldElement T, - final boolean precomputeDoubleOnly) { - return new GroupElement(curve, Representation.P3, X, Y, Z, T, precomputeDoubleOnly); - } - - /** - * Creates a new group element in P1P1 representation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @param T The $T$ coordinate. - * @return The group element in P1P1 representation. - */ - public static GroupElement p1p1( - final Curve curve, - final FieldElement X, - final FieldElement Y, - final FieldElement Z, - final FieldElement T) { - return new GroupElement(curve, Representation.P1P1, X, Y, Z, T); - } - - /** - * Creates a new group element in PRECOMP representation. - * - * @param curve The curve. - * @param ypx The $y + x$ value. - * @param ymx The $y - x$ value. - * @param xy2d The $2 * d * x * y$ value. - * @return The group element in PRECOMP representation. - */ - public static GroupElement precomp( - final Curve curve, final FieldElement ypx, final FieldElement ymx, final FieldElement xy2d) { - return new GroupElement(curve, Representation.PRECOMP, ypx, ymx, xy2d, null); - } - - /** - * Creates a new group element in CACHED representation. - * - * @param curve The curve. - * @param YpX The $Y + X$ value. - * @param YmX The $Y - X$ value. - * @param Z The $Z$ coordinate. - * @param T2d The $2 * d * T$ value. - * @return The group element in CACHED representation. - */ - public static GroupElement cached( - final Curve curve, - final FieldElement YpX, - final FieldElement YmX, - final FieldElement Z, - final FieldElement T2d) { - return new GroupElement(curve, Representation.CACHED, YpX, YmX, Z, T2d); - } - /** Variable is package private only so that tests run. */ final Curve curve; - /** Variable is package private only so that tests run. */ final Representation repr; - /** Variable is package private only so that tests run. */ final FieldElement X; - /** Variable is package private only so that tests run. */ final FieldElement Y; - /** Variable is package private only so that tests run. */ final FieldElement Z; - /** Variable is package private only so that tests run. */ final FieldElement T; - /** * Precomputed table for {@link #scalarMultiply(byte[])}, filled if necessary. * *

Variable is package private only so that tests run. */ final GroupElement[][] precmp; - /** * Precomputed table for , filled if necessary. * @@ -334,6 +193,189 @@ public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleA } } + /** + * Creates a new group element in P2 representation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @return The group element in P2 representation. + */ + public static GroupElement p2( + final Curve curve, final FieldElement X, final FieldElement Y, final FieldElement Z) { + return new GroupElement(curve, Representation.P2, X, Y, Z, null); + } + + /** + * Creates a new group element in P3 representation, without pre-computation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @param T The $T$ coordinate. + * @return The group element in P3 representation. + */ + public static GroupElement p3( + final Curve curve, + final FieldElement X, + final FieldElement Y, + final FieldElement Z, + final FieldElement T) { + return p3(curve, X, Y, Z, T, false); + } + + /** + * Creates a new group element in P3 representation, potentially with pre-computation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @param T The $T$ coordinate. + * @param precomputeDoubleOnly If true, populate dblPrecmp, else set to null. + * @return The group element in P3 representation. + */ + public static GroupElement p3( + final Curve curve, + final FieldElement X, + final FieldElement Y, + final FieldElement Z, + final FieldElement T, + final boolean precomputeDoubleOnly) { + return new GroupElement(curve, Representation.P3, X, Y, Z, T, precomputeDoubleOnly); + } + + /** + * Creates a new group element in P1P1 representation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @param T The $T$ coordinate. + * @return The group element in P1P1 representation. + */ + public static GroupElement p1p1( + final Curve curve, + final FieldElement X, + final FieldElement Y, + final FieldElement Z, + final FieldElement T) { + return new GroupElement(curve, Representation.P1P1, X, Y, Z, T); + } + + /** + * Creates a new group element in PRECOMP representation. + * + * @param curve The curve. + * @param ypx The $y + x$ value. + * @param ymx The $y - x$ value. + * @param xy2d The $2 * d * x * y$ value. + * @return The group element in PRECOMP representation. + */ + public static GroupElement precomp( + final Curve curve, final FieldElement ypx, final FieldElement ymx, final FieldElement xy2d) { + return new GroupElement(curve, Representation.PRECOMP, ypx, ymx, xy2d, null); + } + + /** + * Creates a new group element in CACHED representation. + * + * @param curve The curve. + * @param YpX The $Y + X$ value. + * @param YmX The $Y - X$ value. + * @param Z The $Z$ coordinate. + * @param T2d The $2 * d * T$ value. + * @return The group element in CACHED representation. + */ + public static GroupElement cached( + final Curve curve, + final FieldElement YpX, + final FieldElement YmX, + final FieldElement Z, + final FieldElement T2d) { + return new GroupElement(curve, Representation.CACHED, YpX, YmX, Z, T2d); + } + + /** + * Convert a to radix 16. + * + *

Method is package private only so that tests run. + * + * @param a $= a[0]+256*a[1]+...+256^{31} a[31]$ + * @return 64 bytes, each between -8 and 7 + */ + static byte[] toRadix16(final byte[] a) { + final byte[] e = new byte[64]; + int i; + // Radix 16 notation + for (i = 0; i < 32; i++) { + e[2 * i] = (byte) (a[i] & 15); + e[2 * i + 1] = (byte) ((a[i] >> 4) & 15); + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + int carry = 0; + for (i = 0; i < 63; i++) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 7 */ + return e; + } + + /** + * Calculates a sliding-windows base 2 representation for a given value $a$. To learn more about + * it see [6] page 8. + * + *

Output: $r$ which satisfies $a = r0 * 2^0 + r1 * 2^1 + \dots + r255 * 2^{255}$ with $ri$ in + * $\{-15, -13, -11, -9, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 11, 13, 15\}$ + * + *

Method is package private only so that tests run. + * + * @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$. + * @return The byte array $r$ in the above described form. + */ + static byte[] slide(final byte[] a) { + byte[] r = new byte[256]; + + // Put each bit of 'a' into a separate byte, 0 or 1 + for (int i = 0; i < 256; ++i) { + r[i] = (byte) (1 & (a[i >> 3] >> (i & 7))); + } + + // Note: r[i] will always be odd. + for (int i = 0; i < 256; ++i) { + if (r[i] != 0) { + for (int b = 1; b <= 6 && i + b < 256; ++b) { + // Accumulate bits if possible + if (r[i + b] != 0) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; + r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (int k = i + b; k < 256; ++k) { + if (r[k] == 0) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else break; + } + } + } + } + + return r; + } + /** * Gets the representation of the group element. * @@ -811,36 +853,6 @@ public boolean equals(Object obj) { } } - /** - * Convert a to radix 16. - * - *

Method is package private only so that tests run. - * - * @param a $= a[0]+256*a[1]+...+256^{31} a[31]$ - * @return 64 bytes, each between -8 and 7 - */ - static byte[] toRadix16(final byte[] a) { - final byte[] e = new byte[64]; - int i; - // Radix 16 notation - for (i = 0; i < 32; i++) { - e[2 * i] = (byte) (a[i] & 15); - e[2 * i + 1] = (byte) ((a[i] >> 4) & 15); - } - /* each e[i] is between 0 and 15 */ - /* e[63] is between 0 and 7 */ - int carry = 0; - for (i = 0; i < 63; i++) { - e[i] += carry; - carry = e[i] + 8; - carry >>= 4; - e[i] -= carry << 4; - } - e[63] += carry; - /* each e[i] is between -8 and 7 */ - return e; - } - /** * Constant-time conditional move. * @@ -926,53 +938,6 @@ public GroupElement scalarMultiply(final byte[] a) { return h; } - /** - * Calculates a sliding-windows base 2 representation for a given value $a$. To learn more about - * it see [6] page 8. - * - *

Output: $r$ which satisfies $a = r0 * 2^0 + r1 * 2^1 + \dots + r255 * 2^{255}$ with $ri$ in - * $\{-15, -13, -11, -9, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 11, 13, 15\}$ - * - *

Method is package private only so that tests run. - * - * @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$. - * @return The byte array $r$ in the above described form. - */ - static byte[] slide(final byte[] a) { - byte[] r = new byte[256]; - - // Put each bit of 'a' into a separate byte, 0 or 1 - for (int i = 0; i < 256; ++i) { - r[i] = (byte) (1 & (a[i >> 3] >> (i & 7))); - } - - // Note: r[i] will always be odd. - for (int i = 0; i < 256; ++i) { - if (r[i] != 0) { - for (int b = 1; b <= 6 && i + b < 256; ++b) { - // Accumulate bits if possible - if (r[i + b] != 0) { - if (r[i] + (r[i + b] << b) <= 15) { - r[i] += r[i + b] << b; - r[i + b] = 0; - } else if (r[i] - (r[i + b] << b) >= -15) { - r[i] -= r[i + b] << b; - for (int k = i + b; k < 256; ++k) { - if (r[k] == 0) { - r[k] = 1; - break; - } - r[k] = 0; - } - } else break; - } - } - } - } - - return r; - } - /** * Verify that a point is on the curve. * @@ -1000,4 +965,31 @@ public boolean isOnCurve(Curve curve) { public String toString() { return "[GroupElement\nX=" + X + "\nY=" + Y + "\nZ=" + Z + "\nT=" + T + "\n]"; } + + /** + * Available representations for a group element. + * + *

    + *
  • P2: Projective representation $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$. + *
  • P3: Extended projective representation $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$. + *
  • P3PrecomputedDouble: P3 but with dblPrecmp populated. + *
  • P1P1: Completed representation $((X:Z), (Y:T))$ satisfying $x=X/Z, y=Y/T$. + *
  • PRECOMP: Precomputed representation $(y+x, y-x, 2dxy)$. + *
  • CACHED: Cached representation $(Y+X, Y-X, Z, 2dT)$ + *
+ */ + public enum Representation { + /** Projective ($P^2$): $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$ */ + P2, + /** Extended ($P^3$): $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$ */ + P3, + /** Can only be requested. Results in P3 representation but also populates dblPrecmp. */ + P3PrecomputedDouble, + /** Completed ($P \times P$): $((X:Z),(Y:T))$ satisfying $x=X/Z, y=Y/T$ */ + P1P1, + /** Precomputed (Duif): $(y+x,y-x,2dxy)$ */ + PRECOMP, + /** Cached: $(Y+X,Y-X,Z,2dT)$ */ + CACHED + } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java index 37fb78bab..ff72cb62f 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java @@ -16,6 +16,8 @@ */ public class Ed25519FieldElement extends FieldElement { private static final long serialVersionUID = -2455098303824960263L; + private static final byte[] ZERO = new byte[32]; + /** Variable is package private for encoding. */ final int[] t; @@ -31,8 +33,6 @@ public Ed25519FieldElement(Field f, int[] t) { this.t = t; } - private static final byte[] ZERO = new byte[32]; - /** * Gets a value indicating whether or not the field element is non-zero. * diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java index 7c171690d..774c40a37 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java @@ -9,6 +9,21 @@ *

Reviewed/commented by Bloody Rookie (nemproject@gmx.de) */ public class Ed25519LittleEndianEncoding extends Encoding { + static int load_3(byte[] in, int offset) { + int result = in[offset++] & 0xff; + result |= (in[offset++] & 0xff) << 8; + result |= (in[offset] & 0xff) << 16; + return result; + } + + static long load_4(byte[] in, int offset) { + int result = in[offset++] & 0xff; + result |= (in[offset++] & 0xff) << 8; + result |= (in[offset++] & 0xff) << 16; + result |= in[offset] << 24; + return ((long) result) & 0xffffffffL; + } + /** * Encodes a given field element in its 32 byte representation. This is done in two steps: * @@ -167,21 +182,6 @@ public byte[] encode(FieldElement x) { return s; } - static int load_3(byte[] in, int offset) { - int result = in[offset++] & 0xff; - result |= (in[offset++] & 0xff) << 8; - result |= (in[offset] & 0xff) << 16; - return result; - } - - static long load_4(byte[] in, int offset) { - int result = in[offset++] & 0xff; - result |= (in[offset++] & 0xff) << 8; - result |= (in[offset++] & 0xff) << 16; - result |= in[offset] << 24; - return ((long) result) & 0xffffffffL; - } - /** * Decodes a given field element in its 10 byte $2^{25.5}$ representation. * @@ -190,14 +190,14 @@ static long load_4(byte[] in, int offset) { */ public FieldElement decode(byte[] in) { long h0 = load_4(in, 0); - long h1 = load_3(in, 4) << 6; - long h2 = load_3(in, 7) << 5; - long h3 = load_3(in, 10) << 3; - long h4 = load_3(in, 13) << 2; + long h1 = (long) load_3(in, 4) << 6; + long h2 = (long) load_3(in, 7) << 5; + long h3 = (long) load_3(in, 10) << 3; + long h4 = (long) load_3(in, 13) << 2; long h5 = load_4(in, 16); - long h6 = load_3(in, 20) << 7; - long h7 = load_3(in, 23) << 5; - long h8 = load_3(in, 26) << 4; + long h6 = (long) load_3(in, 20) << 7; + long h7 = (long) load_3(in, 23) << 5; + long h8 = (long) load_3(in, 26) << 4; long h9 = (load_3(in, 29) & 0x7FFFFF) << 2; long carry0; long carry1; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java index f15c33858..209d9f96c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java @@ -42,6 +42,11 @@ public class EdDSANamedCurveTable { private static volatile HashMap curves = new HashMap<>(); + static { + // RFC 8032 + defineCurve(ED_25519_CURVE_SPEC); + } + private static synchronized void putCurve(String name, EdDSANamedCurveSpec curve) { HashMap newCurves = new HashMap<>(curves); newCurves.put(name, curve); @@ -52,11 +57,6 @@ public static void defineCurve(EdDSANamedCurveSpec curve) { putCurve(curve.getName().toLowerCase(Locale.ENGLISH), curve); } - static { - // RFC 8032 - defineCurve(ED_25519_CURVE_SPEC); - } - public static EdDSANamedCurveSpec getByName(String name) { return curves.get(name.toLowerCase(Locale.ENGLISH)); } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java index 01d1fda09..e62d79ce2 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java @@ -43,6 +43,21 @@ public class BigDecimalCodec implements Codec { DataType.MEDIUMBLOB, DataType.LONGBLOB); + static BigInteger getBigInteger(ReadableByteBuf buf, ColumnDecoder column) { + BigInteger val; + if (column.isSigned()) { + val = BigInteger.valueOf(buf.readLong()); + } else { + // need BIG ENDIAN, so reverse order + byte[] bb = new byte[8]; + for (int i = 7; i >= 0; i--) { + bb[i] = buf.readByte(); + } + val = new BigInteger(1, bb); + } + return val; + } + public String className() { return BigDecimal.class.getName(); } @@ -196,21 +211,6 @@ public BigDecimal decodeBinary( } } - static BigInteger getBigInteger(ReadableByteBuf buf, ColumnDecoder column) { - BigInteger val; - if (column.isSigned()) { - val = BigInteger.valueOf(buf.readLong()); - } else { - // need BIG ENDIAN, so reverse order - byte[] bb = new byte[8]; - for (int i = 7; i >= 0; i--) { - bb[i] = buf.readByte(); - } - val = new BigInteger(1, bb); - } - return val; - } - @Override public void encodeText(Writer encoder, Context context, Object value, Calendar cal, Long length) throws IOException { diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java index 4d4ebf199..d5448cccf 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java @@ -21,6 +21,7 @@ public class TimeCodec implements Codec

- - mariadb logo - + + mariadb logo +

# MariaDB java connector @@ -37,19 +37,19 @@ Development snapshot are available on sonatype nexus repository ```script - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + - - org.mariadb.jdbc - mariadb-java-client - 3.2.1-SNAPSHOT - + + org.mariadb.jdbc + mariadb-java-client + 3.2.1-SNAPSHOT + ``` diff --git a/licenseheader.txt b/licenseheader.txt new file mode 100644 index 000000000..6c585c76f --- /dev/null +++ b/licenseheader.txt @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab diff --git a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java index 36ff5b21b..1f290c7bc 100644 --- a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java @@ -214,7 +214,8 @@ public int executeUpdate(String sql) throws SQLException { public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw exceptionFactory() .create( - "executeUpdate(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); + "executeUpdate(String sql, int autoGeneratedKeys) cannot be called on" + + " preparedStatement"); } @Override @@ -228,7 +229,8 @@ public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { public int executeUpdate(String sql, String[] columnNames) throws SQLException { throw exceptionFactory() .create( - "executeUpdate(String sql, String[] columnNames) cannot be called on preparedStatement"); + "executeUpdate(String sql, String[] columnNames) cannot be called on" + + " preparedStatement"); } @Override @@ -241,21 +243,24 @@ public long executeLargeUpdate(String sql) throws SQLException { public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw exceptionFactory() .create( - "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on" + + " preparedStatement"); } @Override public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { throw exceptionFactory() .create( - "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on" + + " preparedStatement"); } @Override public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { throw exceptionFactory() .create( - "executeLargeUpdate(String sql, String[] columnNames) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, String[] columnNames) cannot be called on" + + " preparedStatement"); } // *************************************************************************************************** @@ -1187,8 +1192,7 @@ private void setInternalObject( "HY000", e); } - } else if (obj instanceof Number) { - Number bd = (Number) obj; + } else if (obj instanceof Number bd) { switch (targetSqlType) { case Types.TINYINT: setByte(parameterIndex, bd.byteValue()); diff --git a/src/main/java/org/mariadb/jdbc/Connection.java b/src/main/java/org/mariadb/jdbc/Connection.java index 24067014b..9bb43a272 100644 --- a/src/main/java/org/mariadb/jdbc/Connection.java +++ b/src/main/java/org/mariadb/jdbc/Connection.java @@ -58,6 +58,7 @@ public class Connection implements java.sql.Connection { * @param lock thread safe locker * @param client client object */ + @SuppressWarnings({"this-escape"}) public Connection(Configuration conf, ReentrantLock lock, Client client) { this.conf = conf; this.forceTransactionEnd = @@ -329,11 +330,12 @@ private String getDatabase() throws SQLException { return client.getContext().getDatabase(); } - Statement stmt = createStatement(); - ResultSet rs = stmt.executeQuery("select database()"); - rs.next(); - client.getContext().setDatabase(rs.getString(1)); - return client.getContext().getDatabase(); + try (Statement stmt = createStatement()) { + ResultSet rs = stmt.executeQuery("select database()"); + rs.next(); + client.getContext().setDatabase(rs.getString(1)); + return client.getContext().getDatabase(); + } } private void setDatabase(String database) throws SQLException { @@ -371,29 +373,31 @@ public int getTransactionIsolation() throws SQLException { } } - ResultSet rs = createStatement().executeQuery(sql); - if (rs.next()) { - final String response = rs.getString(1); - switch (response) { - case "REPEATABLE-READ": - return java.sql.Connection.TRANSACTION_REPEATABLE_READ; + try (Statement stmt = createStatement()) { + ResultSet rs = stmt.executeQuery(sql); + if (rs.next()) { + final String response = rs.getString(1); + switch (response) { + case "REPEATABLE-READ": + return java.sql.Connection.TRANSACTION_REPEATABLE_READ; - case "READ-UNCOMMITTED": - return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; + case "READ-UNCOMMITTED": + return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; - case "READ-COMMITTED": - return java.sql.Connection.TRANSACTION_READ_COMMITTED; + case "READ-COMMITTED": + return java.sql.Connection.TRANSACTION_READ_COMMITTED; - case "SERIALIZABLE": - return java.sql.Connection.TRANSACTION_SERIALIZABLE; + case "SERIALIZABLE": + return java.sql.Connection.TRANSACTION_SERIALIZABLE; - default: - throw exceptionFactory.create( - String.format( - "Could not get transaction isolation level: Invalid value \"%s\"", response)); + default: + throw exceptionFactory.create( + String.format( + "Could not get transaction isolation level: Invalid value \"%s\"", response)); + } } + throw exceptionFactory.create("Failed to retrieve transaction isolation"); } - throw exceptionFactory.create("Failed to retrieve transaction isolation"); } @Override @@ -499,7 +503,8 @@ public CallableStatement prepareCall(String sql, int resultSetType, int resultSe Matcher matcher = CALLABLE_STATEMENT_PATTERN.matcher(sql); if (!matcher.matches()) { throw new SQLSyntaxErrorException( - "invalid callable syntax. must be like {[?=]call [(?,?, ...)]}\n but was : " + "invalid callable syntax. must be like {[?=]call [(?,?, ...)]}\n" + + " but was : " + sql); } @@ -927,7 +932,7 @@ public MariaDbSavepoint(final int savepointId) { * @return the numeric ID of this savepoint */ public int getSavepointId() throws SQLException { - if (name != null) { + if (id == null) { throw exceptionFactory.create("Cannot retrieve savepoint id of a named savepoint"); } return id; diff --git a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java index dff720ad0..57ef7a43c 100644 --- a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java +++ b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java @@ -83,9 +83,7 @@ private static int parseIdentifier(char[] part, int startPos, Identifier identif if (ch == '`') { quotes++; } else { - for (int j = 0; j < quotes / 2; j++) { - sb.append('`'); - } + sb.append("`".repeat(quotes / 2)); if (quotes % 2 == 1) { if (ch == '.') { if (identifier.schema != null) { @@ -673,7 +671,8 @@ public ResultSet getPrimaryKeys(String catalog, String schema, String table) thr patternCond(false, sb, "A.TABLE_NAME", table); patternCond(false, sb, "B.TABLE_NAME", table); sb.append( - " AND A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME ORDER BY A.COLUMN_NAME"); + " AND A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME =" + + " B.COLUMN_NAME ORDER BY A.COLUMN_NAME"); return executeQuery(sb.toString()); } @@ -722,11 +721,11 @@ public ResultSet getTables( StringBuilder sb = new StringBuilder( - "SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME," - + " IF(TABLE_TYPE='BASE TABLE' or TABLE_TYPE='SYSTEM VERSIONED', 'TABLE', TABLE_TYPE) as TABLE_TYPE," - + " TABLE_COMMENT REMARKS, NULL TYPE_CAT, NULL TYPE_SCHEM, NULL TYPE_NAME, NULL SELF_REFERENCING_COL_NAME, " - + " NULL REF_GENERATION" - + " FROM INFORMATION_SCHEMA.TABLES"); + "SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, IF(TABLE_TYPE='BASE" + + " TABLE' or TABLE_TYPE='SYSTEM VERSIONED', 'TABLE', TABLE_TYPE) as TABLE_TYPE," + + " TABLE_COMMENT REMARKS, NULL TYPE_CAT, NULL TYPE_SCHEM, NULL TYPE_NAME, NULL" + + " SELF_REFERENCING_COL_NAME, NULL REF_GENERATION FROM" + + " INFORMATION_SCHEMA.TABLES"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( @@ -866,14 +865,11 @@ public ResultSet getColumns( conf.useCatalogTerm() == CatalogTerm.UseCatalog ? "TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM" : "TABLE_CATALOG TABLE_CAT, TABLE_SCHEMA TABLE_SCHEM") - .append( - ", TABLE_NAME, COLUMN_NAME," - + dataTypeClause("COLUMN_TYPE") - + " DATA_TYPE," - + DataTypeClause(conf) - + " TYPE_NAME, " - + " CASE DATA_TYPE" - + " WHEN 'date' THEN 10"); + .append(", TABLE_NAME, COLUMN_NAME,") + .append(dataTypeClause("COLUMN_TYPE")) + .append(" DATA_TYPE,") + .append(DataTypeClause(conf)) + .append(" TYPE_NAME, CASE DATA_TYPE WHEN 'date' THEN 10"); if (supportsFractionalSeconds) { sb.append( " WHEN 'time' THEN " @@ -886,35 +882,36 @@ public ResultSet getColumns( // Older versions do not include the DATETIME_PRECISION column in INFORMATION_SCHEMA.COLUMNS. sb.append(" WHEN 'time' THEN 10 WHEN 'datetime' THEN 19 WHEN 'timestamp' THEN 19"); } - sb.append( - (conf.yearIsDateType() ? "" : " WHEN 'year' THEN 5") - + " ELSE " - + " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," - + Integer.MAX_VALUE - + "), NUMERIC_PRECISION) " - + " END" - + " COLUMN_SIZE, 65535 BUFFER_LENGTH, " - + " CONVERT (CASE DATA_TYPE" - + " WHEN 'year' THEN " - + (conf.yearIsDateType() ? "NUMERIC_SCALE" : "0") - + " WHEN 'tinyint' THEN " - + (conf.tinyInt1isBit() ? "0" : "NUMERIC_SCALE") - + " ELSE NUMERIC_SCALE END, UNSIGNED INTEGER) DECIMAL_DIGITS," - + " 10 NUM_PREC_RADIX, IF(IS_NULLABLE = 'yes',1,0) NULLABLE,COLUMN_COMMENT REMARKS," - + " COLUMN_DEFAULT COLUMN_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, " - + " LEAST(CHARACTER_OCTET_LENGTH," - + Integer.MAX_VALUE - + ") CHAR_OCTET_LENGTH," - + " ORDINAL_POSITION, IS_NULLABLE, NULL SCOPE_CATALOG, NULL SCOPE_SCHEMA, NULL SCOPE_TABLE, NULL SOURCE_DATA_TYPE," - + " IF(EXTRA = 'auto_increment','YES','NO') IS_AUTOINCREMENT, " - + " IF(EXTRA in ('VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO') IS_GENERATEDCOLUMN " - + " FROM INFORMATION_SCHEMA.COLUMNS"); + sb.append((conf.yearIsDateType() ? "" : " WHEN 'year' THEN 5")) + .append( + " ELSE " + + " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + + Integer.MAX_VALUE + + "), NUMERIC_PRECISION) " + + " END" + + " COLUMN_SIZE, 65535 BUFFER_LENGTH, " + + " CONVERT (CASE DATA_TYPE" + + " WHEN 'year' THEN ") + .append((conf.yearIsDateType() ? "NUMERIC_SCALE" : "0")) + .append(" WHEN 'tinyint' THEN ") + .append(conf.tinyInt1isBit() ? "0" : "NUMERIC_SCALE") + .append( + " ELSE NUMERIC_SCALE END, UNSIGNED INTEGER) DECIMAL_DIGITS," + + " 10 NUM_PREC_RADIX, IF(IS_NULLABLE = 'yes',1,0) NULLABLE,COLUMN_COMMENT REMARKS," + + " COLUMN_DEFAULT COLUMN_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, " + + " LEAST(CHARACTER_OCTET_LENGTH," + + Integer.MAX_VALUE + + ") CHAR_OCTET_LENGTH, ORDINAL_POSITION, IS_NULLABLE, NULL SCOPE_CATALOG, NULL" + + " SCOPE_SCHEMA, NULL SCOPE_TABLE, NULL SOURCE_DATA_TYPE, IF(EXTRA =" + + " 'auto_increment','YES','NO') IS_AUTOINCREMENT, IF(EXTRA in ('VIRTUAL'," + + " 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO')" + + " IS_GENERATEDCOLUMN FROM INFORMATION_SCHEMA.COLUMNS"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( true, sb, "TABLE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); firstCondition = patternCond(firstCondition, sb, "TABLE_NAME", tableNamePattern); - firstCondition = patternCond(firstCondition, sb, "COLUMN_NAME", columnNamePattern); + patternCond(firstCondition, sb, "COLUMN_NAME", columnNamePattern); sb.append(" ORDER BY TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION"); return executeQuery(sb.toString()); } @@ -991,7 +988,8 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) .append( conf.useCatalogTerm() == CatalogTerm.UseCatalog ? "KCU.REFERENCED_TABLE_SCHEMA PKTABLE_CAT, NULL PKTABLE_SCHEM" - : "KCU.CONSTRAINT_CATALOG PKTABLE_CAT, KCU.REFERENCED_TABLE_SCHEMA PKTABLE_SCHEM") + : "KCU.CONSTRAINT_CATALOG PKTABLE_CAT, KCU.REFERENCED_TABLE_SCHEMA" + + " PKTABLE_SCHEM") .append( ", KCU.REFERENCED_TABLE_NAME PKTABLE_NAME," + " KCU.REFERENCED_COLUMN_NAME PKCOLUMN_NAME, ") @@ -1000,23 +998,13 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) ? "KCU.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM" : " TABLE_CATALOG FKTABLE_CAT, KCU.TABLE_SCHEMA FKTABLE_SCHEM") .append( - ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME, KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ," - + " CASE update_rule " - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END UPDATE_RULE," - + " CASE DELETE_RULE" - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END DELETE_RULE," - + " RC.CONSTRAINT_NAME FK_NAME," - + " RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME," + + " KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, CASE update_rule WHEN" + + " 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN 'CASCADE' THEN 0 WHEN" + + " 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END UPDATE_RULE, CASE" + + " DELETE_RULE WHEN 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN" + + " 'CASCADE' THEN 0 WHEN 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END" + + " DELETE_RULE, RC.CONSTRAINT_NAME FK_NAME, RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + importedKeyNotDeferrable + " DEFERRABILITY" + " FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU" @@ -1031,7 +1019,7 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) "KCU.REFERENCED_TABLE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); - firstCondition = patternCond(firstCondition, sb, "KCU.REFERENCED_TABLE_NAME", table); + patternCond(firstCondition, sb, "KCU.REFERENCED_TABLE_NAME", table); sb.append(" ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ"); return executeQuery(sb.toString()); @@ -1064,23 +1052,13 @@ public ResultSet getImportedKeysUsingInformationSchema(final String database, St ? "KCU.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM" : "KCU.TABLE_CATALOG FKTABLE_CAT, KCU.TABLE_SCHEMA FKTABLE_SCHEM") .append( - ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME, KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ," - + " CASE update_rule " - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END UPDATE_RULE," - + " CASE DELETE_RULE" - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END DELETE_RULE," - + " RC.CONSTRAINT_NAME FK_NAME," - + " RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME," + + " KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, CASE update_rule WHEN" + + " 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN 'CASCADE' THEN 0 WHEN" + + " 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END UPDATE_RULE, CASE" + + " DELETE_RULE WHEN 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN" + + " 'CASCADE' THEN 0 WHEN 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END" + + " DELETE_RULE, RC.CONSTRAINT_NAME FK_NAME, RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + importedKeyNotDeferrable + " DEFERRABILITY" + " FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU" @@ -1189,8 +1167,8 @@ public ResultSet getBestRowIdentifier( + bestRowSession + " SCOPE, COLUMN_NAME," + dataTypeClause("COLUMN_TYPE") - + " DATA_TYPE, DATA_TYPE TYPE_NAME," - + " IF(NUMERIC_PRECISION IS NULL, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION) COLUMN_SIZE, 0 BUFFER_LENGTH," + + " DATA_TYPE, DATA_TYPE TYPE_NAME, IF(NUMERIC_PRECISION IS NULL," + + " CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION) COLUMN_SIZE, 0 BUFFER_LENGTH," + " NUMERIC_SCALE DECIMAL_DIGITS," + (hasIsGeneratedCol ? ("IF(IS_GENERATED='NEVER'," + bestRowNotPseudo + "," + bestRowPseudo + ")") @@ -1277,9 +1255,9 @@ public ResultSet getPseudoColumns( return connection .createStatement() .executeQuery( - "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' COLUMN_NAME, 0 DATA_TYPE, 0 COLUMN_SIZE, " - + "0 DECIMAL_DIGITS, 10 NUM_PREC_RADIX, ' ' COLUMN_USAGE, ' ' REMARKS, 0 CHAR_OCTET_LENGTH, " - + "'YES' IS_NULLABLE FROM DUAL WHERE 1=0"); + "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' COLUMN_NAME, 0 DATA_TYPE, 0" + + " COLUMN_SIZE, 0 DECIMAL_DIGITS, 10 NUM_PREC_RADIX, ' ' COLUMN_USAGE, ' '" + + " REMARKS, 0 CHAR_OCTET_LENGTH, 'YES' IS_NULLABLE FROM DUAL WHERE 1=0"); } public boolean allProceduresAreCallable() { @@ -1440,9 +1418,10 @@ public String getNumericFunctions() { @Override public String getStringFunctions() { return "ASCII,BIN,BIT_LENGTH,CAST,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONVERT,ELT,EXPORT_SET," - + "EXTRACTVALUE,FIELD,FIND_IN_SET,FORMAT,FROM_BASE64,HEX,INSTR,LCASE,LEFT,LENGTH,LIKE,LOAD_FILE,LOCATE," - + "LOWER,LPAD,LTRIM,MAKE_SET,MATCH AGAINST,MID,NOT LIKE,NOT REGEXP,OCTET_LENGTH,ORD,POSITION,QUOTE," - + "REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SOUNDS LIKE,SPACE,STRCMP,SUBSTR,SUBSTRING," + + "EXTRACTVALUE,FIELD,FIND_IN_SET,FORMAT,FROM_BASE64,HEX,INSTR,LCASE,LEFT,LENGTH,LIKE,LOAD_FILE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH" + + " AGAINST,MID,NOT LIKE,NOT" + + " REGEXP,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SOUNDS" + + " LIKE,SPACE,STRCMP,SUBSTR,SUBSTRING," + "SUBSTRING_INDEX,TO_BASE64,TRIM,UCASE,UNHEX,UPDATEXML,UPPER,WEIGHT_STRING"; } @@ -2072,7 +2051,7 @@ public ResultSet getProcedures(String catalog, String schemaPattern, String proc boolean firstCondition = databaseCond( true, sb, "ROUTINE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); - firstCondition = patternCond(firstCondition, sb, "ROUTINE_NAME", procedureNamePattern); + patternCond(firstCondition, sb, "ROUTINE_NAME", procedureNamePattern); return executeQuery(sb.toString()); } @@ -2178,10 +2157,9 @@ public ResultSet getProcedureColumns( */ StringBuilder sb = new StringBuilder( - "SELECT SPECIFIC_SCHEMA PROCEDURE_CAT, NULL PROCEDURE_SCHEM, SPECIFIC_NAME PROCEDURE_NAME," - + " PARAMETER_NAME COLUMN_NAME, " - + " CASE PARAMETER_MODE " - + " WHEN 'IN' THEN " + "SELECT SPECIFIC_SCHEMA PROCEDURE_CAT, NULL PROCEDURE_SCHEM, SPECIFIC_NAME" + + " PROCEDURE_NAME, PARAMETER_NAME COLUMN_NAME, CASE PARAMETER_MODE WHEN 'IN'" + + " THEN " + procedureColumnIn + " WHEN 'OUT' THEN " + procedureColumnOut @@ -2230,15 +2208,15 @@ public ResultSet getProcedureColumns( + " END `SCALE`," + "10 RADIX," + procedureNullableUnknown - + " NULLABLE,NULL REMARKS,NULL COLUMN_DEF,0 SQL_DATA_TYPE,0 SQL_DATETIME_SUB," - + "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME " - + " FROM INFORMATION_SCHEMA.PARAMETERS"); + + " NULLABLE,NULL REMARKS,NULL COLUMN_DEF,0 SQL_DATA_TYPE,0" + + " SQL_DATETIME_SUB,CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, ''" + + " IS_NULLABLE, SPECIFIC_NAME FROM INFORMATION_SCHEMA.PARAMETERS"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( true, sb, "SPECIFIC_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseCatalog); firstCondition = patternCond(firstCondition, sb, "SPECIFIC_NAME", procedureNamePattern); - firstCondition = patternCond(firstCondition, sb, "PARAMETER_NAME", columnNamePattern); + patternCond(firstCondition, sb, "PARAMETER_NAME", columnNamePattern); sb.append(" ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION"); return executeQuery(sb.toString()); @@ -2351,14 +2329,15 @@ public ResultSet getFunctionColumns( + functionColumnInOut + " ELSE " + functionReturn - + " END COLUMN_TYPE," - + dataTypeClause("DTD_IDENTIFIER") - + " DATA_TYPE," - + "DATA_TYPE TYPE_NAME,NUMERIC_PRECISION `PRECISION`,CHARACTER_MAXIMUM_LENGTH LENGTH,NUMERIC_SCALE SCALE,10 RADIX," + + " END COLUMN_TYPE,") + .append(dataTypeClause("DTD_IDENTIFIER")) + .append( + " DATA_TYPE,DATA_TYPE TYPE_NAME,NUMERIC_PRECISION" + + " `PRECISION`,CHARACTER_MAXIMUM_LENGTH LENGTH,NUMERIC_SCALE SCALE,10 RADIX," + procedureNullableUnknown - + " NULLABLE,NULL REMARKS," - + "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME " - + " FROM INFORMATION_SCHEMA.PARAMETERS"); + + " NULLABLE,NULL REMARKS,CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH" + + " ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME FROM" + + " INFORMATION_SCHEMA.PARAMETERS"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( @@ -2374,7 +2353,8 @@ public ResultSet getFunctionColumns( public ResultSet getSchemas() throws SQLException { if (conf.useCatalogTerm() == CatalogTerm.UseSchema) { return executeQuery( - "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"); + "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM" + + " information_schema.SCHEMATA ORDER BY SCHEMA_NAME"); } return executeQuery("SELECT '' TABLE_SCHEM, '' TABLE_CATALOG FROM DUAL WHERE 1=0"); } @@ -2383,8 +2363,9 @@ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLExce if (conf.useCatalogTerm() == CatalogTerm.UseSchema) { StringBuilder sb = new StringBuilder( - "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM information_schema.SCHEMATA "); - boolean firstCondition = databaseCond(true, sb, "SCHEMA_NAME", schemaPattern, true); + "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM" + + " information_schema.SCHEMATA "); + databaseCond(true, sb, "SCHEMA_NAME", schemaPattern, true); sb.append(" ORDER BY SCHEMA_NAME"); return executeQuery(sb.toString()); } @@ -2401,7 +2382,8 @@ public ResultSet getCatalogs() throws SQLException { public ResultSet getTableTypes() throws SQLException { return executeQuery( - "SELECT 'TABLE' TABLE_TYPE UNION SELECT 'SYSTEM VIEW' TABLE_TYPE UNION SELECT 'VIEW' TABLE_TYPE"); + "SELECT 'TABLE' TABLE_TYPE UNION SELECT 'SYSTEM VIEW' TABLE_TYPE UNION SELECT 'VIEW'" + + " TABLE_TYPE"); } /** @@ -2518,7 +2500,7 @@ public ResultSet getTablePrivileges(String catalog, String schemaPattern, String boolean firstCondition = databaseCond( true, sb, "TABLE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); - firstCondition = patternCond(firstCondition, sb, "TABLE_NAME", tableNamePattern); + patternCond(firstCondition, sb, "TABLE_NAME", tableNamePattern); sb.append(" ORDER BY TABLE_SCHEMA, TABLE_NAME, PRIVILEGE_TYPE "); return executeQuery(sb.toString()); @@ -2673,23 +2655,13 @@ public ResultSet getCrossReference( ? "KCU.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM" : "KCU.TABLE_CATALOG FKTABLE_CAT, KCU.TABLE_SCHEMA FKTABLE_SCHEM") .append( - ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME, KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ," - + " CASE update_rule " - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END UPDATE_RULE," - + " CASE DELETE_RULE" - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END DELETE_RULE," - + " RC.CONSTRAINT_NAME FK_NAME," - + " RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME," + + " KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, CASE update_rule WHEN" + + " 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN 'CASCADE' THEN 0 WHEN" + + " 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END UPDATE_RULE, CASE" + + " DELETE_RULE WHEN 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN" + + " 'CASCADE' THEN 0 WHEN 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END" + + " DELETE_RULE, RC.CONSTRAINT_NAME FK_NAME, RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + importedKeyNotDeferrable + " DEFERRABILITY " + "FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU" @@ -2704,7 +2676,7 @@ public ResultSet getCrossReference( databaseCond(true, sb, "KCU.REFERENCED_TABLE_SCHEMA", parentDatabase, false); firstCondition = databaseCond(firstCondition, sb, "KCU.TABLE_SCHEMA", foreignDatabase, false); firstCondition = patternCond(firstCondition, sb, "KCU.REFERENCED_TABLE_NAME", parentTable); - firstCondition = patternCond(firstCondition, sb, "KCU.TABLE_NAME", foreignTable); + patternCond(firstCondition, sb, "KCU.TABLE_NAME", foreignTable); sb.append("ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ"); return executeQuery(sb.toString()); @@ -3649,8 +3621,8 @@ public ResultSet getUDTs( String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { String sql = - "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' CLASS_NAME, 0 DATA_TYPE, ' ' REMARKS, 0 BASE_TYPE" - + " FROM DUAL WHERE 1=0"; + "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' CLASS_NAME, 0 DATA_TYPE, ' '" + + " REMARKS, 0 BASE_TYPE FROM DUAL WHERE 1=0"; return executeQuery(sql); } @@ -3712,8 +3684,8 @@ public boolean supportsGetGeneratedKeys() { public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { String sql = - "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' SUPERTYPE_CAT, ' ' SUPERTYPE_SCHEM, ' ' SUPERTYPE_NAME" - + " FROM DUAL WHERE 1=0"; + "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' SUPERTYPE_CAT, ' '" + + " SUPERTYPE_SCHEM, ' ' SUPERTYPE_NAME FROM DUAL WHERE 1=0"; return executeQuery(sql); } @@ -3752,7 +3724,8 @@ public ResultSet getSuperTypes(String catalog, String schemaPattern, String type public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { String sql = - "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' SUPERTABLE_NAME FROM DUAL WHERE 1=0"; + "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' SUPERTABLE_NAME FROM DUAL" + + " WHERE 1=0"; return executeQuery(sql); } @@ -3829,13 +3802,11 @@ public ResultSet getAttributes( throws SQLException { String sql = - "SELECT ' ' TYPE_CAT, ' ' TYPE_SCHEM, ' ' TYPE_NAME, ' ' ATTR_NAME, 0 DATA_TYPE," - + " ' ' ATTR_TYPE_NAME, 0 ATTR_SIZE, 0 DECIMAL_DIGITS, 0 NUM_PREC_RADIX, 0 NULLABLE," - + " ' ' REMARKS, ' ' ATTR_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, 0 CHAR_OCTET_LENGTH," - + " 0 ORDINAL_POSITION, ' ' IS_NULLABLE, ' ' SCOPE_CATALOG, ' ' SCOPE_SCHEMA, ' ' SCOPE_TABLE," - + " 0 SOURCE_DATA_TYPE" - + " FROM DUAL " - + " WHERE 1=0"; + "SELECT ' ' TYPE_CAT, ' ' TYPE_SCHEM, ' ' TYPE_NAME, ' ' ATTR_NAME, 0 DATA_TYPE, ' '" + + " ATTR_TYPE_NAME, 0 ATTR_SIZE, 0 DECIMAL_DIGITS, 0 NUM_PREC_RADIX, 0 NULLABLE, ' '" + + " REMARKS, ' ' ATTR_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, 0 CHAR_OCTET_LENGTH, 0" + + " ORDINAL_POSITION, ' ' IS_NULLABLE, ' ' SCOPE_CATALOG, ' ' SCOPE_SCHEMA, ' '" + + " SCOPE_TABLE, 0 SOURCE_DATA_TYPE FROM DUAL WHERE 1=0"; return executeQuery(sql); } @@ -3926,8 +3897,9 @@ public ResultSet getClientInfoProperties() { "ClientUser", "16777215", "", - "The name of the user that the application using the connection is performing work for. " - + "This may not be the same as the user name that was used in establishing the connection." + "The name of the user that the application using the connection is performing work for." + + " This may not be the same as the user name that was used in establishing the" + + " connection." }, new String[] { "ClientHostname", diff --git a/src/main/java/org/mariadb/jdbc/FunctionStatement.java b/src/main/java/org/mariadb/jdbc/FunctionStatement.java index 65c9a07db..444f5e04e 100644 --- a/src/main/java/org/mariadb/jdbc/FunctionStatement.java +++ b/src/main/java/org/mariadb/jdbc/FunctionStatement.java @@ -25,6 +25,7 @@ public class FunctionStatement extends BaseCallableStatement implements Callable * @param resultSetConcurrency concurrency type * @throws SQLException if any error occurs */ + @SuppressWarnings({"this-escape"}) public FunctionStatement( Connection con, String databaseName, diff --git a/src/main/java/org/mariadb/jdbc/HostAddress.java b/src/main/java/org/mariadb/jdbc/HostAddress.java index f7aa232d8..8294331e1 100644 --- a/src/main/java/org/mariadb/jdbc/HostAddress.java +++ b/src/main/java/org/mariadb/jdbc/HostAddress.java @@ -13,10 +13,13 @@ public class HostAddress { /** host address */ public final String host; + /** port */ public int port; + /** primary node */ public Boolean primary; + private Long threadsConnected; private Long threadConnectedTimeout; diff --git a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java index 285fd1b99..d2c7805a9 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java @@ -27,6 +27,7 @@ public class MariaDbPoolConnection implements PooledConnection, XAConnection { * * @param connection connection to retrieve connection options */ + @SuppressWarnings({"this-escape"}) public MariaDbPoolConnection(Connection connection) { this.connection = connection; this.connection.setPoolConnection(this); @@ -231,8 +232,7 @@ public Configuration getConf() { @Override public boolean isSameRM(XAResource xaResource) { - if (xaResource instanceof MariaDbXAResource) { - MariaDbXAResource other = (MariaDbXAResource) xaResource; + if (xaResource instanceof MariaDbXAResource other) { return other.getConf().equals(this.getConf()); } return false; diff --git a/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java b/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java index 89ae134a1..6bc02be06 100644 --- a/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java @@ -48,6 +48,7 @@ public class ServerPreparedStatement extends BasePreparedStatement { * @param defaultFetchSize default fetch size * @throws SQLException if prepare fails */ + @SuppressWarnings({"this-escape"}) public ServerPreparedStatement( String sql, Connection con, diff --git a/src/main/java/org/mariadb/jdbc/Statement.java b/src/main/java/org/mariadb/jdbc/Statement.java index da5bdef0f..83c171d4a 100644 --- a/src/main/java/org/mariadb/jdbc/Statement.java +++ b/src/main/java/org/mariadb/jdbc/Statement.java @@ -44,26 +44,37 @@ public class Statement implements java.sql.Statement { /** result-set type */ protected final int resultSetType; + /** concurrency */ protected final int resultSetConcurrency; + /** thread safe locker */ protected final ReentrantLock lock; + /** can use server query timeout */ protected final boolean canUseServerTimeout; + /** can use server row limitation */ protected final boolean canUseServerMaxRows; + /** connection */ protected final Connection con; + /** required query timeout */ protected int queryTimeout; + /** maximum row number */ protected long maxRows; + /** fetch size */ protected int fetchSize; + /** automatic generated keys result required */ protected int autoGeneratedKeys; + /** close statement on resultset completion */ protected boolean closeOnCompletion; + /** closed flag */ protected boolean closed; diff --git a/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java b/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java index 05335e814..b268e6fd8 100644 --- a/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java +++ b/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java @@ -60,6 +60,7 @@ public class BaseContext implements Context { * @param exceptionFactory connection exception factory * @param prepareCache LRU prepare cache */ + @SuppressWarnings({"this-escape"}) public BaseContext( HostAddress hostAddress, InitialHandshakePacket handshake, diff --git a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java index 842df7e5c..7eb3ff521 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java @@ -62,6 +62,7 @@ public class MultiPrimaryClient implements Client { * @param lock thread locker * @throws SQLException if fail to connect */ + @SuppressWarnings({"this-escape"}) public MultiPrimaryClient(Configuration conf, ReentrantLock lock) throws SQLException { this.conf = conf; this.lock = lock; @@ -149,8 +150,7 @@ protected Client connectHost(boolean readOnly, boolean failFast) throws SQLExcep } } } - - throw lastSqle; + throw (lastSqle != null) ? lastSqle : new SQLNonTransientConnectionException("No host"); } /** @@ -198,7 +198,8 @@ protected void replayIfPossible(Client oldClient, boolean canRedo) throws SQLExc // changing exception to SQLTransientConnectionException throw new SQLTransientConnectionException( String.format( - "Driver has reconnect connection after a communications link failure with %s. In progress transaction was lost", + "Driver has reconnect connection after a communications link failure with %s. In" + + " progress transaction was lost", oldClient.getHostAddress()), "25S03"); } @@ -227,7 +228,8 @@ protected void executeTransactionReplay(Client oldCli) throws SQLException { ctx.getTransactionSaver().clear(); throw new SQLTransientConnectionException( String.format( - "Driver has reconnect connection after a communications link failure with %s. In progress transaction was too big to be replayed, and was lost", + "Driver has reconnect connection after a communications link failure with %s. In" + + " progress transaction was too big to be replayed, and was lost", oldCli.getHostAddress()), "25S03"); } @@ -275,8 +277,9 @@ public void syncNewState(Client oldCli) throws SQLException { } if ((oldCtx.getStateFlag() & ConnectionState.STATE_TRANSACTION_ISOLATION) > 0 - && currentClient.getContext().getTransactionIsolationLevel() - != oldCtx.getTransactionIsolationLevel()) { + && !oldCtx + .getTransactionIsolationLevel() + .equals(currentClient.getContext().getTransactionIsolationLevel())) { String query = "SET SESSION TRANSACTION ISOLATION LEVEL"; switch (oldCtx.getTransactionIsolationLevel()) { case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED: @@ -359,7 +362,8 @@ public List execute( if (message instanceof QueryPacket && ((QueryPacket) message).isCommit()) { throw new SQLTransientConnectionException( String.format( - "Driver has reconnect connection after a communications failure with %s during a COMMIT statement", + "Driver has reconnect connection after a communications failure with %s during a" + + " COMMIT statement", hostAddress), "25S03"); } diff --git a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java index 328a099d8..ac4bd7aba 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java @@ -46,6 +46,7 @@ public class MultiPrimaryReplicaClient extends MultiPrimaryClient { * @param lock thread locker * @throws SQLException if any error occurs */ + @SuppressWarnings({"this-escape"}) public MultiPrimaryReplicaClient(Configuration conf, ReentrantLock lock) throws SQLException { super(conf, lock); primaryClient = currentClient; diff --git a/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java b/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java index 7b02b5438..37ca2d2c7 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java @@ -20,7 +20,7 @@ public final class PrepareCache extends LinkedHashMap> map) throws SQLEx return getObject(columnIndex); } throw exceptionFactory.notSupported( - "Method ResultSet.getObject(int columnIndex, Map> map) not supported for non empty map"); + "Method ResultSet.getObject(int columnIndex, Map> map) not supported for" + + " non empty map"); } @Override @@ -1296,8 +1298,8 @@ public URL getURL(int columnIndex) throws SQLException { StringCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); if (s == null) return null; try { - return new URL(s); - } catch (MalformedURLException e) { + return new URI(s).toURL(); + } catch (Exception e) { throw exceptionFactory.create(String.format("Could not parse '%s' as URL", s)); } } diff --git a/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java b/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java index b7cc19c6f..75b3168a9 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java +++ b/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java @@ -59,6 +59,7 @@ public class StreamingResult extends Result { * @param traceEnable can network log be logged * @throws SQLException if any error occurs */ + @SuppressWarnings({"this-escape"}) public StreamingResult( Statement stmt, boolean binaryProtocol, diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java index fffee66af..02cb0ef6b 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java @@ -70,8 +70,10 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { if (timeout == 0) { throw new FileNotFoundException( fileNotFoundException.getMessage() - + "\nplease consider set connectTimeout option, so connection can retry having access to named pipe. " - + "\n(Named pipe can throw ERROR_PIPE_BUSY error)"); + + "\n" + + "please consider set connectTimeout option, so connection can retry having" + + " access to named pipe. \n" + + "(Named pipe can throw ERROR_PIPE_BUSY error)"); } throw fileNotFoundException; } diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java index 42f50506b..cf17d07e6 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java @@ -255,7 +255,7 @@ public void skipPacket() throws IOException { remaining = lastPacketLength; do { - remaining -= inputStream.skip(remaining); + remaining -= (int) inputStream.skip(remaining); } while (remaining > 0); // *************************************************** @@ -279,7 +279,7 @@ public void skipPacket() throws IOException { remaining = packetLength; do { - remaining -= inputStream.skip(remaining); + remaining -= (int) inputStream.skip(remaining); } while (remaining > 0); lastPacketLength += packetLength; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java index 535b89879..4e85e97df 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java @@ -212,6 +212,7 @@ public static class SockAddr extends Structure { * * @param sunPath path */ + @SuppressWarnings({"this-escape"}) public SockAddr(String sunPath) { byte[] arr = sunPath.getBytes(); sun_path = new byte[arr.length + 1]; diff --git a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java index 3c9d59fe4..1bc5c35fb 100644 --- a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java @@ -184,7 +184,9 @@ default Completion readPacket( .withSql(this.description()) .create( String.format( - "LOAD DATA LOCAL INFILE asked for file '%s' that doesn't correspond to initial query %s. Possible malicious proxy changing server answer ! Command interrupted", + "LOAD DATA LOCAL INFILE asked for file '%s' that doesn't correspond to" + + " initial query %s. Possible malicious proxy changing server" + + " answer ! Command interrupted", fileName, this.description()), "HY000"); } else { diff --git a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java index 0a0fa91ae..68f1528ef 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java @@ -107,7 +107,7 @@ public int encode(Writer writer, Context context, Prepare newPrepareResult) writer.writeByte(p.getBinaryEncodeType()); writer.writeByte(0); if (p.isNull()) { - nullBitsBuffer[i / 8] |= (1 << (i % 8)); + nullBitsBuffer[i / 8] |= (byte) (1 << (i % 8)); } } diff --git a/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java b/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java index 76871b973..8d8bc3006 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java +++ b/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab -// Copyright (c) 2015-2023 MariaDB Corporation Abpackage org.mariadb.jdbc.message.client; +// Copyright (c) 2015-2023 MariaDB Corporation Ab +package org.mariadb.jdbc.message.client; import static org.mariadb.jdbc.util.constants.Capabilities.*; @@ -14,11 +15,13 @@ import org.mariadb.jdbc.message.ClientMessage; import org.mariadb.jdbc.plugin.Credential; import org.mariadb.jdbc.plugin.authentication.standard.NativePasswordPlugin; +import org.mariadb.jdbc.util.ThreadUtils; import org.mariadb.jdbc.util.VersionFactory; /** - * Server handshake response builder. see - * https://mariadb.com/kb/en/connection/#client-handshake-response + * Server handshake response builder. + * + * @see documentation */ public final class HandshakeResponse implements ClientMessage { @@ -100,7 +103,7 @@ private static void writeConnectAttributes( writeStringLength(tmpWriter, System.getProperty("os.name")); writeStringLengthAscii(tmpWriter, _THREAD); - writeStringLength(tmpWriter, Long.toString(Thread.currentThread().getId())); + writeStringLength(tmpWriter, Long.toString(ThreadUtils.getId(Thread.currentThread()))); writeStringLengthAscii(tmpWriter, _JAVA_VENDOR); writeStringLength(tmpWriter, System.getProperty("java.vendor")); diff --git a/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java index 75a0565f6..cd3d3f55b 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java @@ -103,7 +103,7 @@ public int encode(Writer writer, Context context, Prepare newPrepareResult) writer.writeByte(p.getBinaryEncodeType()); writer.writeByte(0); if (p.isNull()) { - nullBitsBuffer[i / 8] |= (1 << (i % 8)); + nullBitsBuffer[i / 8] |= (byte) (1 << (i % 8)); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java index 3222e55da..1d2899a07 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java @@ -31,13 +31,14 @@ public static AuthenticationPlugin get(String type, Configuration conf) throws S for (AuthenticationPlugin implClass : loader) { if (type.equals(implClass.type())) { - if (conf.restrictedAuth() == null || Arrays.stream(authList).anyMatch(type::contains)) { + if (authList == null || Arrays.stream(authList).anyMatch(type::contains)) { return implClass; } else { throw new SQLException( String.format( - "Client restrict authentication plugin to a limited set of authentication plugin and doesn't permit requested plugin ('%s'). " - + "Current list is `restrictedAuth=%s`", + "Client restrict authentication plugin to a limited set of authentication plugin" + + " and doesn't permit requested plugin ('%s'). Current list is" + + " `restrictedAuth=%s`", type, conf.restrictedAuth()), "08004", 1251); diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java index 9c2b0bef1..4d81d18c1 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java @@ -4,7 +4,6 @@ package org.mariadb.jdbc.plugin.authentication.addon.gssapi; import java.io.*; -import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.SQLException; import javax.security.auth.Subject; @@ -14,6 +13,7 @@ import org.mariadb.jdbc.client.ReadableByteBuf; import org.mariadb.jdbc.client.socket.Reader; import org.mariadb.jdbc.client.socket.Writer; +import org.mariadb.jdbc.util.ThreadUtils; /** Basic GSSAPI implementation if waffle is not on classpath */ public class StandardGssapiAuthentication implements GssapiAuth { @@ -34,8 +34,8 @@ public void authenticate( if ("".equals(servicePrincipalName)) { throw new SQLException( - "No principal name defined on server. " - + "Please set server variable \"gssapi-principal-name\" or set option \"servicePrincipalName\"", + "No principal name defined on server. Please set server variable" + + " \"gssapi-principal-name\" or set option \"servicePrincipalName\"", "28000"); } @@ -102,8 +102,9 @@ public void authenticate( } return null; }; - Subject.doAs(mySubject, action); - } catch (PrivilegedActionException exception) { + + ThreadUtils.callAs(mySubject, () -> action); + } catch (Exception exception) { throw new SQLException("GSS-API authentication exception", "28000", 1045, exception); } } else { diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java index 737cdab84..9c3caddc6 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java @@ -219,7 +219,8 @@ public ReadableByteBuf process(Writer out, Reader in, Context context) // read public key from socket if (!conf.allowPublicKeyRetrieval()) { throw new SQLException( - "RSA public key is not available client side (option serverRsaPublicKeyFile not set)", + "RSA public key is not available client side (option serverRsaPublicKeyFile" + + " not set)", "S1009"); } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java index 650e92569..0c0405333 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.plugin.authentication.standard.ed25519; /** diff --git a/src/main/java/org/mariadb/jdbc/plugin/tls/main/DefaultTlsSocketPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/tls/main/DefaultTlsSocketPlugin.java index 802dc1ded..70ccbcaf9 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/tls/main/DefaultTlsSocketPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/tls/main/DefaultTlsSocketPlugin.java @@ -4,8 +4,7 @@ package org.mariadb.jdbc.plugin.tls.main; import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; import java.security.GeneralSecurityException; import java.security.KeyManagementException; import java.security.KeyStore; @@ -62,16 +61,16 @@ private static KeyManager loadClientCerts( private static InputStream loadFromUrl(String keyStoreUrl) throws FileNotFoundException { try { - return new URL(keyStoreUrl).openStream(); - } catch (IOException ioexception) { + return new URI(keyStoreUrl).toURL().openStream(); + } catch (Exception exception) { return new FileInputStream(keyStoreUrl); } } private static InputStream getInputStreamFromPath(String path) throws IOException { try { - return new URL(path).openStream(); - } catch (MalformedURLException e) { + return new URI(path).toURL().openStream(); + } catch (Exception e) { if (path.startsWith("-----")) { return new ByteArrayInputStream(path.getBytes()); } else { @@ -79,9 +78,9 @@ private static InputStream getInputStreamFromPath(String path) throws IOExceptio if (f.exists() && !f.isDirectory()) { return f.toURI().toURL().openStream(); } + throw new IOException( + String.format("File not found for option `serverSslCert` (value: '%s')", path), e); } - throw new IOException( - String.format("Wrong value for option `serverSslCert` (value: '%s')", path), e); } } diff --git a/src/main/java/org/mariadb/jdbc/pool/Pool.java b/src/main/java/org/mariadb/jdbc/pool/Pool.java index 28c4b9ecf..c88778220 100644 --- a/src/main/java/org/mariadb/jdbc/pool/Pool.java +++ b/src/main/java/org/mariadb/jdbc/pool/Pool.java @@ -25,7 +25,6 @@ import org.mariadb.jdbc.util.log.Loggers; /** MariaDB Pool */ -@SuppressWarnings({"unchecked"}) public class Pool implements AutoCloseable, PoolMBean { private static final Logger logger = Loggers.getLogger(Pool.class); @@ -56,6 +55,7 @@ public class Pool implements AutoCloseable, PoolMBean { * @param poolIndex pool index to permit distinction of thread name * @param poolExecutor pools common executor */ + @SuppressWarnings({"this-escape"}) public Pool(Configuration conf, int poolIndex, ScheduledThreadPoolExecutor poolExecutor) { this.conf = conf; @@ -99,9 +99,10 @@ public Pool(Configuration conf, int poolIndex, ScheduledThreadPoolExecutor poolE } waitTimeout = 28800; if (!idleConnections.isEmpty()) { - Statement stmt = idleConnections.getFirst().getConnection().createStatement(); - ResultSet rs = stmt.executeQuery("SELECT @@wait_timeout"); - if (rs.next()) waitTimeout = rs.getInt(1); + try (Statement stmt = idleConnections.getFirst().getConnection().createStatement()) { + ResultSet rs = stmt.executeQuery("SELECT @@wait_timeout"); + if (rs.next()) waitTimeout = rs.getInt(1); + } } } catch (SQLException sqle) { logger.error("error initializing pool connection", sqle); @@ -117,18 +118,17 @@ private void addConnectionRequest() { // ensure to have one worker if was timeout connectionAppender.prestartCoreThread(); - boolean unused = - connectionAppenderQueue.offer( - () -> { - if ((totalConnection.get() < conf.minPoolSize() || pendingRequestNumber.get() > 0) - && totalConnection.get() < conf.maxPoolSize()) { - try { - addConnection(); - } catch (SQLException sqle) { - logger.error("error adding connection to pool", sqle); - } - } - }); + connectionAppenderQueue.offer( + () -> { + if ((totalConnection.get() < conf.minPoolSize() || pendingRequestNumber.get() > 0) + && totalConnection.get() < conf.maxPoolSize()) { + try { + addConnection(); + } catch (SQLException sqle) { + logger.error("error adding connection to pool", sqle); + } + } + }); } } @@ -215,7 +215,8 @@ public void connectionClosed(ConnectionEvent event) { totalConnection.decrementAndGet(); silentCloseConnection(item.getConnection()); logger.debug( - "connection {} removed from pool {} due to error during reset (total:{}, active:{}, pending:{})", + "connection {} removed from pool {} due to error during reset (total:{}," + + " active:{}, pending:{})", item.getConnection().getThreadId(), poolTag, totalConnection.get(), @@ -238,7 +239,7 @@ public void connectionErrorOccurred(ConnectionEvent event) { MariaDbInnerPoolConnection item = ((MariaDbInnerPoolConnection) event.getSource()); totalConnection.decrementAndGet(); - boolean unused = idleConnections.remove(item); + idleConnections.remove(item); // ensure that other connection will be validated before being use // since one connection failed, better to assume the other might as well @@ -247,7 +248,8 @@ public void connectionErrorOccurred(ConnectionEvent event) { silentCloseConnection(item.getConnection()); addConnectionRequest(); logger.debug( - "connection {} removed from pool {} due to having throw a Connection exception (total:{}, active:{}, pending:{})", + "connection {} removed from pool {} due to having throw a Connection exception" + + " (total:{}, active:{}, pending:{})", item.getConnection().getThreadId(), poolTag, totalConnection.get(), @@ -315,7 +317,8 @@ private MariaDbInnerPoolConnection getIdleConnection(long timeout, TimeUnit time addConnectionRequest(); if (logger.isDebugEnabled()) { logger.debug( - "pool {} connection {} removed from pool due to failed validation (total:{}, active:{}, pending:{})", + "pool {} connection {} removed from pool due to failed validation (total:{}," + + " active:{}, pending:{})", poolTag, item.getConnection().getThreadId(), totalConnection.get(), @@ -441,7 +444,7 @@ public void close() { connectionAppender.shutdown(); try { - boolean unused = connectionAppender.awaitTermination(10, TimeUnit.SECONDS); + connectionAppender.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException i) { // eat } @@ -485,7 +488,7 @@ public void close() { } catch (Exception exception) { // eat } - boolean unused = connectionRemover.awaitTermination(10, TimeUnit.SECONDS); + connectionRemover.awaitTermination(10, TimeUnit.SECONDS); } } catch (Exception e) { // eat diff --git a/src/main/java/org/mariadb/jdbc/util/StringUtils.java b/src/main/java/org/mariadb/jdbc/util/StringUtils.java index d4205684b..022c7f3ef 100644 --- a/src/main/java/org/mariadb/jdbc/util/StringUtils.java +++ b/src/main/java/org/mariadb/jdbc/util/StringUtils.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.util; public final class StringUtils { diff --git a/src/main/java/org/mariadb/jdbc/util/log/LoggerHelper.java b/src/main/java/org/mariadb/jdbc/util/log/LoggerHelper.java index 19081138b..7ac4eb7c2 100644 --- a/src/main/java/org/mariadb/jdbc/util/log/LoggerHelper.java +++ b/src/main/java/org/mariadb/jdbc/util/log/LoggerHelper.java @@ -62,7 +62,8 @@ public static String hex(byte[] bytes, int offset, int dataLength, int trunkLeng sb.append( " +--------------------------------------------------+\n" + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n" - + "+------+--------------------------------------------------+------------------+\n|000000| "); + + "+------+--------------------------------------------------+------------------+\n" + + "|000000| "); while (pos < logLength + offset) { int byteValue = bytes[pos] & 0xFF; @@ -110,9 +111,9 @@ public static String hex(byte[] bytes, int offset, int dataLength, int trunkLeng } private static String mediumIntTohexa(int value) { - String st = Integer.toHexString(value * 16); - while (st.length() < 6) st = "0" + st; - return st; + StringBuilder st = new StringBuilder(Integer.toHexString(value * 16)); + while (st.length() < 6) st.insert(0, "0"); + return st.toString(); } /** diff --git a/src/main/java11/org/mariadb/jdbc/client/SocketHelper.java b/src/main/java11/org/mariadb/jdbc/client/SocketHelper.java index fb4a1ebe4..9aedde698 100644 --- a/src/main/java11/org/mariadb/jdbc/client/SocketHelper.java +++ b/src/main/java11/org/mariadb/jdbc/client/SocketHelper.java @@ -10,6 +10,8 @@ import org.mariadb.jdbc.Configuration; public class SocketHelper { + public SocketHelper() { } + public static void setSocketOption(final Configuration conf, final Socket socket) throws IOException { socket.setTcpNoDelay(true); socket.setSoTimeout(conf.socketTimeout()); diff --git a/src/test/java/org/mariadb/jdbc/integration/BatchTest.java b/src/test/java/org/mariadb/jdbc/integration/BatchTest.java index 25cdd765e..5ba617699 100644 --- a/src/test/java/org/mariadb/jdbc/integration/BatchTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/BatchTest.java @@ -59,7 +59,8 @@ public void wrongParameter(Connection con) throws SQLException { e.getMessage().contains("Parameter at position 2 is not set") || e.getMessage() .contains( - "batch set of parameters differ from previous set. All parameters must be set")); + "batch set of parameters differ from previous set. All parameters must be" + + " set")); } prep.setInt(1, 5); diff --git a/src/test/java/org/mariadb/jdbc/integration/ClientPreparedStatementParsingTest.java b/src/test/java/org/mariadb/jdbc/integration/ClientPreparedStatementParsingTest.java index bcc555bdc..14ab94bed 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ClientPreparedStatementParsingTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ClientPreparedStatementParsingTest.java @@ -12,13 +12,13 @@ public class ClientPreparedStatementParsingTest extends Common { - private void checkParsing(String sql, int paramNumber, String[] partsMulti) throws Exception { + private void checkParsing(String sql, int paramNumber, String[] partsMulti) { boolean noBackslashEscapes = (sharedConn.getContext().getServerStatus() & ServerStatus.NO_BACKSLASH_ESCAPES) > 0; ClientParser parser = ClientParser.parameterParts(sql, noBackslashEscapes); assertEquals(paramNumber, parser.getParamCount()); int pos = 0; - int paramPos = parser.getQuery().length; + int paramPos; for (int i = 0; i < parser.getParamPositions().size(); i++) { paramPos = parser.getParamPositions().get(i); assertEquals(partsMulti[i], new String(parser.getQuery(), pos, paramPos - pos)); @@ -40,7 +40,8 @@ public void stringEscapeParsing() throws Exception { @Test public void testRewritableWithConstantParameter() throws Exception { checkParsing( - "INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY UPDATE col2=col2+10", + "INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY" + + " UPDATE col2=col2+10", 2, new String[] { "INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ", @@ -74,7 +75,8 @@ public void testComment() throws Exception { @Test public void testRewritableWithConstantParameterAndParamAfterValue() throws Exception { checkParsing( - "INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY UPDATE col2=?", + "INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ?, 5, ?, 8) ON DUPLICATE KEY" + + " UPDATE col2=?", 3, new String[] { "INSERT INTO TABLE(col1,col2,col3,col4, col5) VALUES (9, ", @@ -267,10 +269,18 @@ public void testValuesForPartition() throws Exception { @Test public void testParse() throws Exception { checkParsing( - "INSERT INTO `myTable` VALUES ('\\n\"\\'', \"'\\\n\\\"\") \n // comment\n , ('a', 'b') # EOL comment", + "INSERT INTO `myTable` VALUES ('\\n" + + "\"\\'', \"'\\\n" + + "\\\"\") \n" + + " // comment\n" + + " , ('a', 'b') # EOL comment", 0, new String[] { - "INSERT INTO `myTable` VALUES ('\\n\"\\'', \"'\\\n\\\"\") \n // comment\n , ('a', 'b') # EOL comment" + "INSERT INTO `myTable` VALUES ('\\n" + + "\"\\'', \"'\\\n" + + "\\\"\") \n" + + " // comment\n" + + " , ('a', 'b') # EOL comment" }); } } diff --git a/src/test/java/org/mariadb/jdbc/integration/ConfigurationTest.java b/src/test/java/org/mariadb/jdbc/integration/ConfigurationTest.java index 31c49df93..517fefce7 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ConfigurationTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ConfigurationTest.java @@ -15,7 +15,8 @@ public static void begin() throws SQLException { drop(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE testSessionVariable(id int not null primary key auto_increment, test varchar(10))"); + "CREATE TABLE testSessionVariable(id int not null primary key auto_increment, test" + + " varchar(10))"); stmt.execute("FLUSH TABLES"); } diff --git a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java index 9754ecbc9..8557888b7 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ConnectionTest.java @@ -126,7 +126,8 @@ public void initSQL() throws SQLException { public void nativeSQL() throws SQLException { String[] inputs = new String[] { - "select {fn TIMESTAMPDIFF ( SQL_TSI_HOUR, {fn convert('SQL_', SQL_INTEGER)})}, {fn TIMESTAMPDIFF (HOUR, {fn convert ('sQL_' , SQL_INTEGER)})}", + "select {fn TIMESTAMPDIFF ( SQL_TSI_HOUR, {fn convert('SQL_', SQL_INTEGER)})}, {fn" + + " TIMESTAMPDIFF (HOUR, {fn convert ('sQL_' , SQL_INTEGER)})}", "{call foo({fn now()})} //end", "{call foo({fn '{' now()} /* {test}# \"'\" */) \"\\\"'#\" '\"\\''} #{test2}", "{ call foo({fn now()})}", @@ -150,7 +151,8 @@ public void nativeSQL() throws SQLException { }; String[] outputs = new String[] { - "select TIMESTAMPDIFF ( HOUR, convert('SQL_', INTEGER)), TIMESTAMPDIFF (HOUR, convert ('sQL_' , INTEGER))", + "select TIMESTAMPDIFF ( HOUR, convert('SQL_', INTEGER)), TIMESTAMPDIFF (HOUR, convert " + + " ('sQL_' , INTEGER))", "call foo(now()) //end", "call foo('{' now() /* {test}# \"'\" */) \"\\\"'#\" '\"\\'' #{test2}", "call foo(now())", @@ -176,9 +178,11 @@ public void nativeSQL() throws SQLException { assertEquals(outputs[i], sharedConn.nativeSQL(inputs[i])); } assertEquals( - "INSERT INTO TEST_SYNTAX_ERROR(str_value, json_value) VALUES ('abc\\\\', '{\"data\": \"test\"}')", + "INSERT INTO TEST_SYNTAX_ERROR(str_value, json_value) VALUES ('abc\\\\', '{\"data\":" + + " \"test\"}')", sharedConn.nativeSQL( - "INSERT INTO TEST_SYNTAX_ERROR(str_value, json_value) VALUES ('abc\\\\', '{\"data\": \"test\"}')")); + "INSERT INTO TEST_SYNTAX_ERROR(str_value, json_value) VALUES ('abc\\\\', '{\"data\":" + + " \"test\"}')")); try { sharedConn.nativeSQL("{call foo({fn now())}"); @@ -321,7 +325,8 @@ public void doubleBackslash() throws SQLException { + " json_value MEDIUMTEXT CHARACTER SET utf8mb4 NOT NULL, " + " PRIMARY KEY ( id ))"); stmt.execute( - "INSERT INTO TEST_SYNTAX_ERROR(str_value, json_value) VALUES ('abc\\\\', '{\"data\": \"test\"}')"); + "INSERT INTO TEST_SYNTAX_ERROR(str_value, json_value) VALUES ('abc\\\\', '{\"data\":" + + " \"test\"}')"); } @Test @@ -462,7 +467,8 @@ public void run() { SQLException.class, () -> stmt.executeQuery( - "select * from information_schema.columns as c1, information_schema.tables, information_schema.tables as t2")); + "select * from information_schema.columns as c1, information_schema.tables," + + " information_schema.tables as t2")); } } @@ -499,7 +505,8 @@ public void testConnectionAttributes() throws Exception { Statement attributeStatement = connection.createStatement(); ResultSet result = attributeStatement.executeQuery( - "select * from performance_schema.session_connect_attrs where ATTR_NAME='_server_host' and processlist_id = connection_id()"); + "select * from performance_schema.session_connect_attrs where" + + " ATTR_NAME='_server_host' and processlist_id = connection_id()"); while (result.next()) { String strVal = result.getString("ATTR_VALUE"); assertEquals(Configuration.parse(mDefUrl).addresses().get(0).host, strVal); @@ -890,8 +897,8 @@ public void windowsNamedPipeCancel() throws SQLException { () -> { exec.execute(new StatementTest.CancelThread(stmt)); stmt.execute( - "select * from information_schema.columns as c1, information_schema.tables, information_schema" - + ".tables as t2"); + "select * from information_schema.columns as c1, information_schema.tables," + + " information_schema.tables as t2"); exec.shutdown(); }, "Query execution was interrupted"); @@ -1128,8 +1135,8 @@ public void testProperRollback() throws Exception { try { stmt.execute("CREATE TABLE tx_prim_key(id int not null primary key) engine=innodb"); stmt.execute( - "CREATE TABLE tx_fore_key (id int not null primary key, id_ref int not null, " - + "foreign key (id_ref) references tx_prim_key(id) on delete restrict on update restrict) " + "CREATE TABLE tx_fore_key (id int not null primary key, id_ref int not null, foreign" + + " key (id_ref) references tx_prim_key(id) on delete restrict on update restrict) " + "engine=innodb"); stmt.executeUpdate("insert into tx_prim_key(id) values(32)"); stmt.executeUpdate("insert into tx_fore_key(id, id_ref) values(42, 32)"); diff --git a/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java b/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java index 10a3cc2a6..f5b0e2006 100644 --- a/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/DataSourceTest.java @@ -51,14 +51,17 @@ private void testDs(MariaDbDataSource ds) throws SQLException { try { con1 = ds.getPooledConnection(); con2 = ds.getPooledConnection(); - - ResultSet rs1 = con1.getConnection().createStatement().executeQuery("SELECT 1"); - ResultSet rs2 = con2.getConnection().createStatement().executeQuery("SELECT 2"); - while (rs1.next()) { - assertEquals(1, rs1.getInt(1)); - } - while (rs2.next()) { - assertEquals(2, rs2.getInt(1)); + try (Statement stmt = con1.getConnection().createStatement()) { + ResultSet rs1 = stmt.executeQuery("SELECT 1"); + try (Statement stmt2 = con2.getConnection().createStatement()) { + ResultSet rs2 = stmt2.executeQuery("SELECT 2"); + while (rs1.next()) { + assertEquals(1, rs1.getInt(1)); + } + while (rs2.next()) { + assertEquals(2, rs2.getInt(1)); + } + } } } finally { @@ -72,15 +75,18 @@ private void testDs(MariaDbDataSource ds) throws SQLException { conx1 = ds.getXAConnection(); conx2 = ds.getXAConnection(); - ResultSet rs1 = conx1.getConnection().createStatement().executeQuery("SELECT 1"); - ResultSet rs2 = conx2.getConnection().createStatement().executeQuery("SELECT 2"); - while (rs1.next()) { - assertEquals(1, rs1.getInt(1)); - } - while (rs2.next()) { - assertEquals(2, rs2.getInt(1)); + try (Statement stmt = conx1.getConnection().createStatement()) { + ResultSet rs1 = stmt.executeQuery("SELECT 1"); + try (Statement stmt2 = conx2.getConnection().createStatement()) { + ResultSet rs2 = stmt2.executeQuery("SELECT 2"); + while (rs1.next()) { + assertEquals(1, rs1.getInt(1)); + } + while (rs2.next()) { + assertEquals(2, rs2.getInt(1)); + } + } } - } finally { if (conx1 != null) con1.close(); if (conx2 != null) con2.close(); @@ -99,19 +105,19 @@ public void basic2() throws SQLException { ds.setLoginTimeout(50); assertEquals(50, ds.getLoginTimeout()); - assertThrows(SQLException.class, () -> ds.getConnection()); + assertThrows(SQLException.class, ds::getConnection); assertThrows(SQLException.class, () -> ds.getConnection("user", "password")); - assertThrows(SQLException.class, () -> ds.getPooledConnection()); + assertThrows(SQLException.class, ds::getPooledConnection); assertThrows(SQLException.class, () -> ds.getPooledConnection("user", "password")); - assertThrows(SQLException.class, () -> ds.getXAConnection()); + assertThrows(SQLException.class, ds::getXAConnection); assertThrows(SQLException.class, () -> ds.getXAConnection("user", "password")); ds.setUser("dd"); assertEquals("dd", ds.getUser()); ds.setPassword("pwd"); - assertThrows(SQLException.class, () -> ds.getConnection()); - assertThrows(SQLException.class, () -> ds.getPooledConnection()); + assertThrows(SQLException.class, ds::getConnection); + assertThrows(SQLException.class, ds::getPooledConnection); assertThrows(SQLException.class, () -> ds.setUrl("jdbc:wrong://d")); @@ -140,7 +146,8 @@ public void switchUser() throws SQLException { stmt.execute("GRANT SELECT ON " + sharedConn.getCatalog() + ".* TO 'dsUser'@'%'"); } else { stmt.execute( - "CREATE USER 'dsUser'@'%' IDENTIFIED WITH mysql_native_password BY 'MySup8%rPassw@ord'"); + "CREATE USER 'dsUser'@'%' IDENTIFIED WITH mysql_native_password BY" + + " 'MySup8%rPassw@ord'"); stmt.execute("GRANT SELECT ON " + sharedConn.getCatalog() + ".* TO 'dsUser'@'%'"); } } else { diff --git a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java index 5f2c7d190..f4b9b16c4 100644 --- a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java @@ -52,45 +52,30 @@ public static void initClass() throws SQLException { + "t6 time(6))"); stmt.execute("CREATE TABLE json_test(t1 JSON)"); stmt.execute( - "CREATE PROCEDURE testMetaCatalog(x int, out y int) COMMENT 'comments' \nBEGIN\nSELECT 1;end\n"); + "CREATE PROCEDURE testMetaCatalog(x int, out y int) COMMENT 'comments' \n" + + "BEGIN\n" + + "SELECT 1;end\n"); stmt.execute( - "CREATE TABLE IF NOT EXISTS dbpk_test(val varchar(20), id1 int not null, id2 int not null,primary key(id1, " - + "id2)) engine=innodb"); + "CREATE TABLE IF NOT EXISTS dbpk_test(val varchar(20), id1 int not null, id2 int not" + + " null,primary key(id1, id2)) engine=innodb"); stmt.execute("CREATE TABLE IF NOT EXISTS datetime_test(dt datetime)"); stmt.execute( - "CREATE TABLE IF NOT EXISTS `manycols`(" - + " `tiny` tinyint(4) DEFAULT NULL," - + " `tiny_uns` tinyint(3) unsigned DEFAULT NULL," - + " `small` smallint(6) DEFAULT NULL," - + " `small_uns` smallint(5) unsigned DEFAULT NULL," - + " `medium` mediumint(9) DEFAULT NULL," - + " `medium_uns` mediumint(8) unsigned DEFAULT NULL," - + " `int_col` int(11) DEFAULT NULL," - + " `int_col_uns` int(10) unsigned DEFAULT NULL," - + " `big` bigint(20) DEFAULT NULL," - + " `big_uns` bigint(20) unsigned DEFAULT NULL," - + " `decimal_col` decimal(10,5) DEFAULT NULL," - + " `fcol` float DEFAULT NULL," - + " `fcol_uns` float unsigned DEFAULT NULL," - + " `dcol` double DEFAULT NULL," - + " `dcol_uns` double unsigned DEFAULT NULL," - + " `date_col` date DEFAULT NULL," - + " `time_col` time DEFAULT NULL," - + " `timestamp_col` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," - + " `year_col` year(4) DEFAULT NULL," - + " `bit_col` bit(5) DEFAULT NULL," - + " `char_col` char(5) DEFAULT NULL," - + " `varchar_col` varchar(10) DEFAULT NULL," - + " `binary_col` binary(10) DEFAULT NULL," - + " `varbinary_col` varbinary(10) DEFAULT NULL," - + " `tinyblob_col` tinyblob," - + " `blob_col` blob," - + " `mediumblob_col` mediumblob," - + " `longblob_col` longblob," - + " `tinytext_col` tinytext," - + " `text_col` text," - + " `mediumtext_col` mediumtext," - + " `longtext_col` longtext)"); + "CREATE TABLE IF NOT EXISTS `manycols`( `tiny` tinyint(4) DEFAULT NULL, `tiny_uns`" + + " tinyint(3) unsigned DEFAULT NULL, `small` smallint(6) DEFAULT NULL, `small_uns`" + + " smallint(5) unsigned DEFAULT NULL, `medium` mediumint(9) DEFAULT NULL, " + + " `medium_uns` mediumint(8) unsigned DEFAULT NULL, `int_col` int(11) DEFAULT NULL, " + + " `int_col_uns` int(10) unsigned DEFAULT NULL, `big` bigint(20) DEFAULT NULL, " + + " `big_uns` bigint(20) unsigned DEFAULT NULL, `decimal_col` decimal(10,5) DEFAULT" + + " NULL, `fcol` float DEFAULT NULL, `fcol_uns` float unsigned DEFAULT NULL, `dcol`" + + " double DEFAULT NULL, `dcol_uns` double unsigned DEFAULT NULL, `date_col` date" + + " DEFAULT NULL, `time_col` time DEFAULT NULL, `timestamp_col` timestamp NOT NULL" + + " DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `year_col` year(4) DEFAULT" + + " NULL, `bit_col` bit(5) DEFAULT NULL, `char_col` char(5) DEFAULT NULL, " + + " `varchar_col` varchar(10) DEFAULT NULL, `binary_col` binary(10) DEFAULT NULL, " + + " `varbinary_col` varbinary(10) DEFAULT NULL, `tinyblob_col` tinyblob, `blob_col`" + + " blob, `mediumblob_col` mediumblob, `longblob_col` longblob, `tinytext_col`" + + " tinytext, `text_col` text, `mediumtext_col` mediumtext, `longtext_col`" + + " longtext)"); stmt.execute("CREATE TABLE IF NOT EXISTS ytab(y year)"); stmt.execute( "CREATE TABLE IF NOT EXISTS maxcharlength(maxcharlength char(1)) character set utf8"); @@ -103,19 +88,18 @@ public static void initClass() throws SQLException { stmt.execute("drop table if exists cross1"); stmt.execute("create table cross1 (id int not null primary key, val varchar(20))"); stmt.execute( - "create table cross2 (id int not null, id2 int not null, " - + "id_ref0 int, foreign key (id_ref0) references cross1(id), UNIQUE unik_name (id, id2))"); + "create table cross2 (id int not null, id2 int not null, id_ref0 int, foreign key" + + " (id_ref0) references cross1(id), UNIQUE unik_name (id, id2))"); stmt.execute( - "create table cross3 (id int not null primary key, " - + "id_ref1 int, id_ref2 int, foreign key fk_my_name (id_ref1, id_ref2) references cross2(id, id2) on " - + "update cascade)"); + "create table cross3 (id int not null primary key, id_ref1 int, id_ref2 int, foreign key" + + " fk_my_name (id_ref1, id_ref2) references cross2(id, id2) on update cascade)"); stmt.execute( - "create table getBestRowIdentifier1(i int not null primary key auto_increment, id int, " - + "id_ref1 int, id_ref2 int, foreign key fk_my_name_1 (id_ref1, id_ref2) references cross2(id, id2) on " - + "update cascade, UNIQUE getBestRowIdentifier_unik (id))"); + "create table getBestRowIdentifier1(i int not null primary key auto_increment, id int," + + " id_ref1 int, id_ref2 int, foreign key fk_my_name_1 (id_ref1, id_ref2) references" + + " cross2(id, id2) on update cascade, UNIQUE getBestRowIdentifier_unik (id))"); stmt.execute( - "create table getBestRowIdentifier2(id_ref0 int not null, " - + "id_ref1 int, id_ref2 int not null, UNIQUE (id_ref1, id_ref2) , UNIQUE (id_ref0, id_ref2))"); + "create table getBestRowIdentifier2(id_ref0 int not null, id_ref1 int, id_ref2 int not" + + " null, UNIQUE (id_ref1, id_ref2) , UNIQUE (id_ref0, id_ref2))"); stmt.execute( "CREATE TABLE IF NOT EXISTS get_index_info(\n" + " no INT NOT NULL AUTO_INCREMENT,\n" @@ -195,9 +179,9 @@ public void primaryKeyTest2() throws SQLException { stmt.execute("drop table if exists primarykeytest1"); stmt.execute("CREATE TABLE primarykeytest1 ( id1 integer, constraint pk primary key(id1))"); stmt.execute( - "CREATE TABLE primarykeytest2 (id2a integer, id2b integer, constraint pk primary key(id2a, id2b), " - + "constraint fk1 foreign key(id2a) references primarykeytest1(id1), constraint fk2 foreign key(id2b) " - + "references primarykeytest1(id1))"); + "CREATE TABLE primarykeytest2 (id2a integer, id2b integer, constraint pk primary key(id2a," + + " id2b), constraint fk1 foreign key(id2a) references primarykeytest1(id1), " + + " constraint fk2 foreign key(id2b) references primarykeytest1(id1))"); DatabaseMetaData dbmd = sharedConn.getMetaData(); ResultSet rs = dbmd.getPrimaryKeys(sharedConn.getCatalog(), null, "primarykeytest2"); @@ -223,9 +207,10 @@ public void primaryKeyTest2Schema() throws SQLException { stmt.execute("drop table if exists primarykeytest1"); stmt.execute("CREATE TABLE primarykeytest1 ( id1 integer, constraint pk primary key(id1))"); stmt.execute( - "CREATE TABLE primarykeytest2 (id2a integer, id2b integer, constraint pk primary key(id2a, id2b), " - + "constraint fk1 foreign key(id2a) references primarykeytest1(id1), constraint fk2 foreign key(id2b) " - + "references primarykeytest1(id1))"); + "CREATE TABLE primarykeytest2 (id2a integer, id2b integer, constraint pk primary" + + " key(id2a, id2b), constraint fk1 foreign key(id2a) references" + + " primarykeytest1(id1), constraint fk2 foreign key(id2b) references" + + " primarykeytest1(id1))"); DatabaseMetaData dbmd = con.getMetaData(); ResultSet rs = dbmd.getPrimaryKeys(con.getCatalog(), null, "primarykeytest2"); @@ -388,7 +373,8 @@ private void getImportedKeys( + " UNIQUE unik_name (category, id) )"); st.execute( - "CREATE TABLE `cus``tomer` (id INT NOT NULL, id2 INT NOT NULL, PRIMARY KEY (id), UNIQUE unikConst (id2))"); + "CREATE TABLE `cus``tomer` (id INT NOT NULL, id2 INT NOT NULL, PRIMARY KEY (id), UNIQUE" + + " unikConst (id2))"); String constraint = "ON UPDATE SET DEFAULT ON DELETE SET DEFAULT"; if (!isMariaDBServer() || !minVersion(10, 5, 0)) constraint = "ON UPDATE CASCADE ON DELETE CASCADE"; @@ -753,8 +739,8 @@ public void importedKeysTest() throws SQLException { "create table fore_key0 (id int not null primary key, " + "id_ref0 int, foreign key (id_ref0) references prim_key(id)) engine=innodb"); stmt.execute( - "create table fore_key1 (id int not null primary key, " - + "id_ref1 int, foreign key (id_ref1) references prim_key(id) on update cascade) engine=innodb"); + "create table fore_key1 (id int not null primary key, id_ref1 int, foreign key (id_ref1)" + + " references prim_key(id) on update cascade) engine=innodb"); DatabaseMetaData dbmd = sharedConn.getMetaData(); ResultSet rs = dbmd.getImportedKeys(sharedConn.getCatalog(), null, "fore_key0"); @@ -808,8 +794,8 @@ public void testGetTables() throws SQLException { "create table fore_key0 (id int not null primary key, " + "id_ref0 int, foreign key (id_ref0) references prim_key(id)) engine=innodb"); stmt.execute( - "create table fore_key1 (id int not null primary key, " - + "id_ref1 int, foreign key (id_ref1) references prim_key(id) on update cascade) engine=innodb"); + "create table fore_key1 (id int not null primary key, id_ref1 int, foreign key (id_ref1)" + + " references prim_key(id) on update cascade) engine=innodb"); DatabaseMetaData dbmd = sharedConn.getMetaData(); ResultSet rs = dbmd.getTables(null, null, "prim_key", null); @@ -889,14 +875,16 @@ public void testGetColumns() throws SQLException { Statement stmt = sharedConn.createStatement(); if (minVersion(10, 2, 0) || !isMariaDBServer()) { stmt.execute( - "CREATE TABLE IF NOT EXISTS `ta\nble'getcolumns`(" - + "a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT AS (CHAR_LENGTH(b)) VIRTUAL, " - + "d VARCHAR(5) AS (left(b,5)) STORED) CHARACTER SET 'utf8mb4'"); + "CREATE TABLE IF NOT EXISTS `ta\n" + + "ble'getcolumns`(a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT AS" + + " (CHAR_LENGTH(b)) VIRTUAL, d VARCHAR(5) AS (left(b,5)) STORED) CHARACTER SET" + + " 'utf8mb4'"); } else { stmt.execute( - "CREATE TABLE IF NOT EXISTS `ta\nble'getcolumns`(" - + "a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT AS (CHAR_LENGTH(b)) VIRTUAL, " - + "d VARCHAR(5) AS (left(b,5)) PERSISTENT) CHARACTER SET 'utf8mb4'"); + "CREATE TABLE IF NOT EXISTS `ta\n" + + "ble'getcolumns`(a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT AS" + + " (CHAR_LENGTH(b)) VIRTUAL, d VARCHAR(5) AS (left(b,5)) PERSISTENT) CHARACTER SET" + + " 'utf8mb4'"); } DatabaseMetaData dbmd = sharedConn.getMetaData(); @@ -1018,14 +1006,16 @@ public void testGetColumnsSchema() throws SQLException { stmt.execute( "CREATE TABLE IF NOT EXISTS " + database - + ".`ta\nble'getcolumns`(" - + "a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT AS (CHAR_LENGTH(b)) VIRTUAL, " - + "d VARCHAR(5) AS (left(b,5)) STORED) CHARACTER SET 'utf8mb4'"); + + ".`ta\n" + + "ble'getcolumns`(a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT" + + " AS (CHAR_LENGTH(b)) VIRTUAL, d VARCHAR(5) AS (left(b,5)) STORED) CHARACTER SET" + + " 'utf8mb4'"); } else { stmt.execute( - "CREATE TABLE IF NOT EXISTS \"+database+\".`ta\nble'getcolumns`(" - + "a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT AS (CHAR_LENGTH(b)) VIRTUAL, " - + "d VARCHAR(5) AS (left(b,5)) PERSISTENT) CHARACTER SET 'utf8mb4'"); + "CREATE TABLE IF NOT EXISTS \"+database+\".`ta\n" + + "ble'getcolumns`(a INT NOT NULL primary key auto_increment, b VARCHAR(32), c INT" + + " AS (CHAR_LENGTH(b)) VIRTUAL, d VARCHAR(5) AS (left(b,5)) PERSISTENT) CHARACTER" + + " SET 'utf8mb4'"); } DatabaseMetaData dbmd = con.getMetaData(); @@ -1293,7 +1283,10 @@ private void testResultSetColumns(ResultSet rs, String spec) throws SQLException + ",expected String"); break; case "decimal": - assertEquals(Types.DECIMAL, columnType, "invalid type " + assertEquals( + Types.DECIMAL, + columnType, + "invalid type " + columnType + "( " + rsmd.getColumnTypeName(col) @@ -1330,7 +1323,10 @@ private void testResultSetColumns(ResultSet rs, String spec) throws SQLException break; case "null": - assertEquals(Types.NULL, columnType, "invalid type " + assertEquals( + Types.NULL, + columnType, + "invalid type " + columnType + " for " + rsmd.getColumnLabel(col) @@ -1364,12 +1360,11 @@ public void getSchemas() throws SQLException { public void getAttributesBasic() throws Exception { testResultSetColumns( sharedConn.getMetaData().getAttributes(null, null, null, null), - "TYPE_CAT String,TYPE_SCHEM String,TYPE_NAME String," - + "ATTR_NAME String,DATA_TYPE int,ATTR_TYPE_NAME String,ATTR_SIZE int,DECIMAL_DIGITS int," - + "NUM_PREC_RADIX int,NULLABLE int,REMARKS String,ATTR_DEF String,SQL_DATA_TYPE int," - + "SQL_DATETIME_SUB int, CHAR_OCTET_LENGTH int,ORDINAL_POSITION int,IS_NULLABLE String," - + "SCOPE_CATALOG String,SCOPE_SCHEMA String," - + "SCOPE_TABLE String,SOURCE_DATA_TYPE short"); + "TYPE_CAT String,TYPE_SCHEM String,TYPE_NAME String,ATTR_NAME String,DATA_TYPE" + + " int,ATTR_TYPE_NAME String,ATTR_SIZE int,DECIMAL_DIGITS int,NUM_PREC_RADIX" + + " int,NULLABLE int,REMARKS String,ATTR_DEF String,SQL_DATA_TYPE int,SQL_DATETIME_SUB" + + " int, CHAR_OCTET_LENGTH int,ORDINAL_POSITION int,IS_NULLABLE String,SCOPE_CATALOG" + + " String,SCOPE_SCHEMA String,SCOPE_TABLE String,SOURCE_DATA_TYPE short"); } @Test @@ -1574,8 +1569,9 @@ public void getClientInfoPropertiesBasic() throws Exception { assertEquals(0x00ffffff, rs.getInt(2)); assertEquals("", rs.getString(3)); assertEquals( - "The name of the user that the application using the connection is performing work for. " - + "This may not be the same as the user name that was used in establishing the connection.", + "The name of the user that the application using the connection is performing work for." + + " This may not be the same as the user name that was used in establishing the" + + " connection.", rs.getString(4)); assertTrue(rs.next()); @@ -1628,11 +1624,11 @@ public void getProcedureColumnsBasic() throws SQLException { Assumptions.assumeTrue(!isXpand()); testResultSetColumns( sharedConn.getMetaData().getProcedureColumns(null, null, null, null), - "PROCEDURE_CAT String,PROCEDURE_SCHEM String,PROCEDURE_NAME String,COLUMN_NAME String ," - + "COLUMN_TYPE short,DATA_TYPE int,TYPE_NAME String,PRECISION int,LENGTH int,SCALE short," - + "RADIX short,NULLABLE short,REMARKS String,COLUMN_DEF String,SQL_DATA_TYPE int," - + "SQL_DATETIME_SUB int ,CHAR_OCTET_LENGTH int," - + "ORDINAL_POSITION int,IS_NULLABLE String,SPECIFIC_NAME String"); + "PROCEDURE_CAT String,PROCEDURE_SCHEM String,PROCEDURE_NAME String,COLUMN_NAME String" + + " ,COLUMN_TYPE short,DATA_TYPE int,TYPE_NAME String,PRECISION int,LENGTH int,SCALE" + + " short,RADIX short,NULLABLE short,REMARKS String,COLUMN_DEF String,SQL_DATA_TYPE" + + " int,SQL_DATETIME_SUB int ,CHAR_OCTET_LENGTH int,ORDINAL_POSITION int,IS_NULLABLE" + + " String,SPECIFIC_NAME String"); } @Test @@ -1641,10 +1637,10 @@ public void getFunctionColumnsBasic() throws SQLException { Assumptions.assumeFalse(isXpand()); testResultSetColumns( sharedConn.getMetaData().getFunctionColumns(null, null, null, null), - "FUNCTION_CAT String,FUNCTION_SCHEM String,FUNCTION_NAME String,COLUMN_NAME String,COLUMN_TYPE short," - + "DATA_TYPE int,TYPE_NAME String,PRECISION int,LENGTH int,SCALE short,RADIX short," - + "NULLABLE short,REMARKS String,CHAR_OCTET_LENGTH int,ORDINAL_POSITION int," - + "IS_NULLABLE String,SPECIFIC_NAME String"); + "FUNCTION_CAT String,FUNCTION_SCHEM String,FUNCTION_NAME String,COLUMN_NAME" + + " String,COLUMN_TYPE short,DATA_TYPE int,TYPE_NAME String,PRECISION int,LENGTH" + + " int,SCALE short,RADIX short,NULLABLE short,REMARKS String,CHAR_OCTET_LENGTH" + + " int,ORDINAL_POSITION int,IS_NULLABLE String,SPECIFIC_NAME String"); } @Test @@ -1681,7 +1677,8 @@ public void getVersionColumnsBasic() throws SQLException { public void getPrimaryKeysBasic() throws SQLException { testResultSetColumns( sharedConn.getMetaData().getPrimaryKeys(null, null, null), - "TABLE_CAT String,TABLE_SCHEM String,TABLE_NAME String,COLUMN_NAME String,KEY_SEQ short,PK_NAME String"); + "TABLE_CAT String,TABLE_SCHEM String,TABLE_NAME String,COLUMN_NAME String,KEY_SEQ" + + " short,PK_NAME String"); } @Test @@ -1689,9 +1686,10 @@ public void getImportedKeysBasic() throws SQLException { Assumptions.assumeFalse(isXpand()); testResultSetColumns( sharedConn.getMetaData().getImportedKeys(null, null, ""), - "PKTABLE_CAT String,PKTABLE_SCHEM String,PKTABLE_NAME String, PKCOLUMN_NAME String,FKTABLE_CAT String," - + "FKTABLE_SCHEM String,FKTABLE_NAME String,FKCOLUMN_NAME String,KEY_SEQ short," - + "UPDATE_RULE short,DELETE_RULE short,FK_NAME String,PK_NAME String,DEFERRABILITY short"); + "PKTABLE_CAT String,PKTABLE_SCHEM String,PKTABLE_NAME String, PKCOLUMN_NAME" + + " String,FKTABLE_CAT String,FKTABLE_SCHEM String,FKTABLE_NAME String,FKCOLUMN_NAME" + + " String,KEY_SEQ short,UPDATE_RULE short,DELETE_RULE short,FK_NAME String,PK_NAME" + + " String,DEFERRABILITY short"); } @Test @@ -1699,9 +1697,10 @@ public void getExportedKeysBasic() throws SQLException { Assumptions.assumeFalse(isXpand()); testResultSetColumns( sharedConn.getMetaData().getExportedKeys(null, null, ""), - "PKTABLE_CAT String,PKTABLE_SCHEM String,PKTABLE_NAME String, PKCOLUMN_NAME String,FKTABLE_CAT String," - + "FKTABLE_SCHEM String,FKTABLE_NAME String,FKCOLUMN_NAME String,KEY_SEQ short," - + "UPDATE_RULE short, DELETE_RULE short,FK_NAME String,PK_NAME String,DEFERRABILITY short"); + "PKTABLE_CAT String,PKTABLE_SCHEM String,PKTABLE_NAME String, PKCOLUMN_NAME" + + " String,FKTABLE_CAT String,FKTABLE_SCHEM String,FKTABLE_NAME String,FKCOLUMN_NAME" + + " String,KEY_SEQ short,UPDATE_RULE short, DELETE_RULE short,FK_NAME String,PK_NAME" + + " String,DEFERRABILITY short"); } @Test @@ -1709,9 +1708,10 @@ public void getCrossReferenceBasic() throws SQLException { Assumptions.assumeFalse(isXpand()); testResultSetColumns( sharedConn.getMetaData().getCrossReference(null, null, "", null, null, ""), - "PKTABLE_CAT String,PKTABLE_SCHEM String,PKTABLE_NAME String, PKCOLUMN_NAME String,FKTABLE_CAT String," - + "FKTABLE_SCHEM String,FKTABLE_NAME String,FKCOLUMN_NAME String,KEY_SEQ short," - + "UPDATE_RULE short,DELETE_RULE short,FK_NAME String,PK_NAME String,DEFERRABILITY short"); + "PKTABLE_CAT String,PKTABLE_SCHEM String,PKTABLE_NAME String, PKCOLUMN_NAME" + + " String,FKTABLE_CAT String,FKTABLE_SCHEM String,FKTABLE_NAME String,FKCOLUMN_NAME" + + " String,KEY_SEQ short,UPDATE_RULE short,DELETE_RULE short,FK_NAME String,PK_NAME" + + " String,DEFERRABILITY short"); } @Test @@ -1866,8 +1866,8 @@ public void getSuperTypesBasic() throws SQLException { public void getFunctionsBasic() throws SQLException { testResultSetColumns( sharedConn.getMetaData().getFunctions(null, null, null), - "FUNCTION_CAT String, FUNCTION_SCHEM String,FUNCTION_NAME String,REMARKS String,FUNCTION_TYPE short, " - + "SPECIFIC_NAME String"); + "FUNCTION_CAT String, FUNCTION_SCHEM String,FUNCTION_NAME String,REMARKS" + + " String,FUNCTION_TYPE short, SPECIFIC_NAME String"); } @Test @@ -1906,11 +1906,11 @@ public void testGetTypeInfoBasic() throws SQLException { testResultSetColumns( rs, - "TYPE_NAME String,DATA_TYPE int,PRECISION int,LITERAL_PREFIX String," - + "LITERAL_SUFFIX String,CREATE_PARAMS String, NULLABLE short,CASE_SENSITIVE boolean," - + "SEARCHABLE short,UNSIGNED_ATTRIBUTE boolean,FIXED_PREC_SCALE boolean, " - + "AUTO_INCREMENT boolean, LOCAL_TYPE_NAME String,MINIMUM_SCALE short,MAXIMUM_SCALE short," - + "SQL_DATA_TYPE int,SQL_DATETIME_SUB int, NUM_PREC_RADIX int"); + "TYPE_NAME String,DATA_TYPE int,PRECISION int,LITERAL_PREFIX String,LITERAL_SUFFIX" + + " String,CREATE_PARAMS String, NULLABLE short,CASE_SENSITIVE boolean,SEARCHABLE" + + " short,UNSIGNED_ATTRIBUTE boolean,FIXED_PREC_SCALE boolean, AUTO_INCREMENT boolean," + + " LOCAL_TYPE_NAME String,MINIMUM_SCALE short,MAXIMUM_SCALE short,SQL_DATA_TYPE" + + " int,SQL_DATETIME_SUB int, NUM_PREC_RADIX int"); } @Test diff --git a/src/test/java/org/mariadb/jdbc/integration/FunctionTest.java b/src/test/java/org/mariadb/jdbc/integration/FunctionTest.java index c98be5686..45a711311 100644 --- a/src/test/java/org/mariadb/jdbc/integration/FunctionTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/FunctionTest.java @@ -21,7 +21,8 @@ public void basicFunction() throws SQLException { Statement stmt = sharedConn.createStatement(); stmt.execute("DROP FUNCTION IF EXISTS basic_function"); stmt.execute( - "CREATE FUNCTION basic_function (t1 INT, t2 INT unsigned) RETURNS INT DETERMINISTIC RETURN t1 * t2;"); + "CREATE FUNCTION basic_function (t1 INT, t2 INT unsigned) RETURNS INT DETERMINISTIC RETURN" + + " t1 * t2;"); try (CallableStatement callableStatement = sharedConn.prepareCall("{? = call basic_function(?,?)}")) { callableStatement.registerOutParameter(1, JDBCType.INTEGER); @@ -40,7 +41,7 @@ public void basicFunction() throws SQLException { callableStatement.clearParameters(); assertThrowsContains( SQLTransientConnectionException.class, - () -> callableStatement.execute(), + callableStatement::execute, "Parameter at position 1 is not set"); } @@ -166,7 +167,8 @@ public void functionToString() throws SQLException { callableStatement.setLong(2, 10L); callableStatement.setBytes(3, new byte[] {(byte) 'a', (byte) 'b'}); assertEquals( - "FunctionStatement{sql:'SELECT basic_function(?,?)', parameters:[null,10,_binary 'ab']}", + "FunctionStatement{sql:'SELECT basic_function(?,?)', parameters:[null,10,_binary" + + " 'ab']}", callableStatement.toString()); } } diff --git a/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java b/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java index cb7ee644f..a262cd668 100644 --- a/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java @@ -10,6 +10,7 @@ import java.util.Locale; import org.junit.jupiter.api.*; +@SuppressWarnings("ResultOfMethodCallIgnored") public class LocalInfileTest extends Common { @BeforeAll public static void beforeAll2() throws SQLException { @@ -21,9 +22,11 @@ public static void beforeAll2() throws SQLException { stmt.execute("CREATE TABLE ttlocal(id int, test varchar(100))"); stmt.execute("CREATE TABLE ldinfile(a varchar(10))"); stmt.execute( - "CREATE TABLE `infile`(`a` varchar(50) DEFAULT NULL, `b` varchar(50) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1"); + "CREATE TABLE `infile`(`a` varchar(50) DEFAULT NULL, `b` varchar(50) DEFAULT NULL)" + + " ENGINE=InnoDB DEFAULT CHARSET=latin1"); stmt.execute( - "CREATE TABLE big_load_data_infile(id int not null primary key auto_increment, name char(20)) ENGINE=myisam"); + "CREATE TABLE big_load_data_infile(id int not null primary key auto_increment, name" + + " char(20)) ENGINE=myisam"); stmt.execute("FLUSH TABLES"); } @@ -73,7 +76,7 @@ public void bigLoadDataInfileTest() throws SQLException, IOException { } @Test - public void streamInBatch() throws SQLException, IOException { + public void streamInBatch() throws SQLException { Assumptions.assumeFalse((!isMariaDBServer() && minVersion(8, 0, 3))); Assumptions.assumeTrue( !"skysql".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv"))); @@ -97,7 +100,8 @@ public void streamInBatch() throws SQLException, IOException { try (PreparedStatement prep = sharedConn.prepareStatement( - "LOAD DATA LOCAL INFILE 'dummy.tsv' INTO TABLE LocalInfileInputStreamTest2 (id, test)")) { + "LOAD DATA LOCAL INFILE 'dummy.tsv' INTO TABLE LocalInfileInputStreamTest2 (id," + + " test)")) { inputStream = new ByteArrayInputStream(builder.getBytes()); ((org.mariadb.jdbc.Statement) prep).setLocalInfileInputStream(inputStream); prep.addBatch(); @@ -111,7 +115,8 @@ public void streamInBatch() throws SQLException, IOException { } try (PreparedStatement prep = sharedConnBinary.prepareStatement( - "LOAD DATA LOCAL INFILE 'dummy.tsv' INTO TABLE LocalInfileInputStreamTest2 (id, test)")) { + "LOAD DATA LOCAL INFILE 'dummy.tsv' INTO TABLE LocalInfileInputStreamTest2 (id," + + " test)")) { inputStream = new ByteArrayInputStream(builder.getBytes()); ((org.mariadb.jdbc.Statement) prep).setLocalInfileInputStream(inputStream); prep.addBatch(); @@ -142,8 +147,10 @@ public void throwExceptions() throws Exception { SQLException.class, () -> stmt.execute( - "LOAD DATA LOCAL INFILE 'someFile' INTO TABLE LocalInfileInputStreamTest2 (id, test)"), - "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile commands"); + "LOAD DATA LOCAL INFILE 'someFile' INTO TABLE LocalInfileInputStreamTest2 (id," + + " test)"), + "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile" + + " commands"); stmt.addBatch( "LOAD DATA LOCAL INFILE 'someFile' INTO TABLE LocalInfileInputStreamTest2 (id, test)"); stmt.addBatch("SET UNIQUE_CHECKS=1"); @@ -156,7 +163,8 @@ public void throwExceptions() throws Exception { assertTrue( e.getMessage() .contains( - "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile commands")); + "Local infile is disabled by connector. Enable `allowLocalInfile` to allow" + + " local infile commands")); assertNotNull(e.getCause()); assertEquals(e.getCause().getMessage(), e.getMessage()); assertEquals(((SQLException) e.getCause()).getSQLState(), e.getSQLState()); @@ -170,7 +178,8 @@ public void throwExceptions() throws Exception { Common.assertThrowsContains( SQLException.class, prep::execute, - "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile commands"); + "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile" + + " commands"); } } } @@ -187,7 +196,8 @@ public void wrongFile() throws Exception { SQLException.class, () -> stmt.execute( - "LOAD DATA LOCAL INFILE 'someFile' INTO TABLE LocalInfileInputStreamTest2 (id, test)"), + "LOAD DATA LOCAL INFILE 'someFile' INTO TABLE LocalInfileInputStreamTest2 (id," + + " test)"), "Could not send file : someFile"); assertTrue(con.isValid(1)); } @@ -350,13 +360,15 @@ public void loadDataValidationFails(boolean prepStmt) throws Exception { } try (PreparedStatement prep = con.prepareStatement( - "/* test */ LOAD DATA LOCAL INFILE 'j' INTO TABLE LocalInfileInputStreamTest2 (id, test)")) { + "/* test */ LOAD DATA LOCAL INFILE 'j' INTO TABLE LocalInfileInputStreamTest2 (id," + + " test)")) { assertThrowsContains(SQLException.class, () -> prep.execute(), "Could not send file : j"); } // special test comment inside LOAD DATA LOCAL are not checked, resulting in error try (PreparedStatement prep = con.prepareStatement( - "LOAD /**g*/ DATA LOCAL INFILE 'h' INTO TABLE LocalInfileInputStreamTest2 (id, test)")) { + "LOAD /**g*/ DATA LOCAL INFILE 'h' INTO TABLE LocalInfileInputStreamTest2 (id," + + " test)")) { assertThrowsContains( SQLException.class, () -> prep.execute(), diff --git a/src/test/java/org/mariadb/jdbc/integration/LoggingTest.java b/src/test/java/org/mariadb/jdbc/integration/LoggingTest.java index 095ef28f3..7070e2340 100644 --- a/src/test/java/org/mariadb/jdbc/integration/LoggingTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/LoggingTest.java @@ -154,8 +154,7 @@ void certLogging() throws Exception { logger.addAppender(fa); String certString = - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDfDCCAmSgAwIBAgIURZJQVOWv+oaj+MLlHWc1B0TnOaowDQYJKoZIhvcNAQEL\n" + "BQAwUjELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjESMBAG\n" + "A1UECgwJQWNtZSxJbmMuMRUwEwYDVQQDDAxBY21lIFJvb3QgQ0EwIBcNMjEwMzMw\n" @@ -188,22 +187,22 @@ void certLogging() throws Exception { verifyExceptionEqual( "local.host", cert, - "DNS host \"local.host\" doesn't correspond to certificate " - + "CN \"*.mariadb.org\" and SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); + "DNS host \"local.host\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); HostnameVerifier.verify("127.0.0.1", cert, -1); verifyExceptionEqual( "127.0.0.2", cert, - "IPv4 host \"127.0.0.2\" doesn't correspond to certificate " - + "CN \"*.mariadb.org\" and SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); + "IPv4 host \"127.0.0.2\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); HostnameVerifier.verify("2001:db8:3902:3468:0:0:0:443", cert, -1); verifyExceptionEqual( "2001:db8:1::", cert, - "IPv6 host \"2001:db8:1::\" doesn't correspond to certificate " - + "CN \"*.mariadb.org\" and SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); + "IPv6 host \"2001:db8:1::\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); try { String contents = new String(Files.readAllBytes(Paths.get(tempFile.getPath()))); @@ -215,7 +214,8 @@ void certLogging() throws Exception { "IPv4 verification of hostname : type=IP value=127.0.0.1 to 127.0.0.2")); assertTrue( contents.contains( - "IPv6 verification of hostname : type=IP value=2001:db8:3902:3468:0:0:0:443 to 2001:db8:1::")); + "IPv6 verification of hostname : type=IP value=2001:db8:3902:3468:0:0:0:443 to" + + " 2001:db8:1::")); logger.setLevel(initialLevel); logger.detachAppender(fa); diff --git a/src/test/java/org/mariadb/jdbc/integration/MultiHostTest.java b/src/test/java/org/mariadb/jdbc/integration/MultiHostTest.java index b995abd70..c5c9852bd 100644 --- a/src/test/java/org/mariadb/jdbc/integration/MultiHostTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/MultiHostTest.java @@ -270,13 +270,13 @@ public void masterFailover() throws Exception { con.isValid(1000); } - Thread.sleep(100); + Thread.sleep(1000); // same in transaction try (Connection con = (Connection) DriverManager.getConnection( url - + "&waitReconnectTimeout=300&retriesAllDown=10&connectTimeout=20&deniedListTimeout=20&socketTimeout=10")) { + + "&waitReconnectTimeout=300&retriesAllDown=10&connectTimeout=20&deniedListTimeout=20&socketTimeout=100")) { Statement stmt = con.createStatement(); stmt.execute("START TRANSACTION"); stmt.execute("SET @con=1"); @@ -313,7 +313,7 @@ public void masterFailover() throws Exception { assertTrue(e.getMessage().contains("In progress transaction was lost")); } } - Thread.sleep(50); + Thread.sleep(100); // with transaction replay try (Connection con = (Connection) diff --git a/src/test/java/org/mariadb/jdbc/integration/MultiQueriesTest.java b/src/test/java/org/mariadb/jdbc/integration/MultiQueriesTest.java index ea5cccf9e..2d9b4d8cb 100644 --- a/src/test/java/org/mariadb/jdbc/integration/MultiQueriesTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/MultiQueriesTest.java @@ -91,6 +91,7 @@ public void allowMultiQueriesFetchTest() throws SQLException { } @Test + @SuppressWarnings("try") public void quitWhileStreaming() throws SQLException { // XPAND doesn't support DO command Assumptions.assumeFalse(isXpand()); @@ -99,7 +100,8 @@ public void quitWhileStreaming() throws SQLException { Statement stmt = connection.createStatement(); stmt.setFetchSize(1); stmt.executeQuery( - "DO 2;SELECT * from AllowMultiQueriesTest;SELECT * from AllowMultiQueriesTest; DO 1; SELECT 2"); + "DO 2;SELECT * from AllowMultiQueriesTest;SELECT * from AllowMultiQueriesTest; DO 1; SELECT" + + " 2"); connection.abort(Runnable::run); connection = createCon("&allowMultiQueries=true"); diff --git a/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java b/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java index 2bbdb9d10..ae9f528b6 100644 --- a/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/PoolDataSourceTest.java @@ -8,7 +8,6 @@ import java.lang.management.ManagementFactory; import java.sql.*; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -50,7 +49,8 @@ public static void beforeClassDataSourceTest() throws SQLException { stmt.execute("GRANT SELECT ON " + sharedConn.getCatalog() + ".* TO 'poolUser'@'%'"); } stmt.execute( - "CREATE TABLE testResetRollback(id int not null primary key auto_increment, test varchar(20))"); + "CREATE TABLE testResetRollback(id int not null primary key auto_increment, test" + + " varchar(20))"); stmt.execute("FLUSH TABLES"); stmt.execute("FLUSH PRIVILEGES"); } @@ -117,17 +117,20 @@ private void testDs(MariaDbPoolDataSource ds) throws SQLException { try { con1 = ds.getPooledConnection(); con2 = ds.getPooledConnection(); - - ResultSet rs1 = con1.getConnection().createStatement().executeQuery("SELECT 1"); - ResultSet rs2 = con2.getConnection().createStatement().executeQuery("SELECT 2"); - while (rs1.next()) { - assertEquals(1, rs1.getInt(1)); - } - while (rs2.next()) { - assertEquals(2, rs2.getInt(1)); + try (Statement st1 = con1.getConnection().createStatement()) { + try (Statement st2 = con2.getConnection().createStatement()) { + ResultSet rs1 = st1.executeQuery("SELECT 1"); + ResultSet rs2 = st2.executeQuery("SELECT 2"); + while (rs1.next()) { + assertEquals(1, rs1.getInt(1)); + } + while (rs2.next()) { + assertEquals(2, rs2.getInt(1)); + } + } } long threadId = ((org.mariadb.jdbc.Connection) con2.getConnection()).getThreadId(); - if (con2 != null) con2.getConnection().close(); + con2.getConnection().close(); con2 = ds.getPooledConnection(); assertEquals(threadId, ((org.mariadb.jdbc.Connection) con2.getConnection()).getThreadId()); } finally { @@ -140,14 +143,17 @@ private void testDs(MariaDbPoolDataSource ds) throws SQLException { try { conx1 = ds.getXAConnection(); conx2 = ds.getXAConnection(); - - ResultSet rs1 = conx1.getConnection().createStatement().executeQuery("SELECT 1"); - ResultSet rs2 = conx2.getConnection().createStatement().executeQuery("SELECT 2"); - while (rs1.next()) { - assertEquals(1, rs1.getInt(1)); - } - while (rs2.next()) { - assertEquals(2, rs2.getInt(1)); + try (Statement st1 = conx1.getConnection().createStatement()) { + try (Statement st2 = conx2.getConnection().createStatement()) { + ResultSet rs1 = st1.executeQuery("SELECT 1"); + ResultSet rs2 = st2.executeQuery("SELECT 2"); + while (rs1.next()) { + assertEquals(1, rs1.getInt(1)); + } + while (rs2.next()) { + assertEquals(2, rs2.getInt(1)); + } + } } } finally { @@ -168,19 +174,19 @@ public void basic2() throws SQLException { ds.setLoginTimeout(50); assertEquals(50, ds.getLoginTimeout()); - assertThrows(SQLException.class, () -> ds.getConnection()); + assertThrows(SQLException.class, ds::getConnection); assertThrows(SQLException.class, () -> ds.getConnection("user", "password")); - assertThrows(SQLException.class, () -> ds.getPooledConnection()); + assertThrows(SQLException.class, ds::getPooledConnection); assertThrows(SQLException.class, () -> ds.getPooledConnection("user", "password")); - assertThrows(SQLException.class, () -> ds.getXAConnection()); + assertThrows(SQLException.class, ds::getXAConnection); assertThrows(SQLException.class, () -> ds.getXAConnection("user", "password")); ds.setUser("dd"); assertEquals("dd", ds.getUser()); ds.setPassword("pwd"); - assertThrows(SQLException.class, () -> ds.getConnection()); - assertThrows(SQLException.class, () -> ds.getPooledConnection()); + assertThrows(SQLException.class, ds::getConnection); + assertThrows(SQLException.class, ds::getPooledConnection); assertThrows(SQLException.class, () -> ds.setUrl("jdbc:wrong://d")); @@ -487,7 +493,7 @@ public void testIdleTimeout() throws Throwable { ObjectName name = objectNames.iterator().next(); checkJmxInfo(server, name, 0, 3, 3); - List initialThreadIds = pool.testGetConnectionIdleThreadIds(); + pool.testGetConnectionIdleThreadIds(); Thread.sleep(200); // must still have 3 connections, but must be other ones @@ -587,7 +593,6 @@ public void ensureUsingPool() throws Exception { new LinkedBlockingQueue<>(5000), new PoolThreadFactory("testPool")); - final long start = System.currentTimeMillis(); Set threadIds = new HashSet<>(); for (int i = 0; i < 500; i++) { connectionAppender.execute( @@ -659,7 +664,8 @@ public void wrongUrlHandling() throws SQLException { assertTrue( sqle.getMessage() .contains( - "No connection available within the specified time (option 'connectTimeout': 500 ms)")); + "No connection available within the specified time (option 'connectTimeout':" + + " 500 ms)")); } } } @@ -689,7 +695,7 @@ public void poolWithUser() throws SQLException { try (MariaDbPoolDataSource pool = new MariaDbPoolDataSource( mDefUrl + "&maxPoolSize=1&poolName=myPool&allowPublicKeyRetrieval")) { - long threadId = 0; + long threadId; try (Connection conn = pool.getConnection()) { conn.isValid(1); threadId = ((org.mariadb.jdbc.Connection) conn).getThreadId(); @@ -707,6 +713,7 @@ public void poolWithUser() throws SQLException { } @Test + @SuppressWarnings("try") public void various() throws SQLException { Common.assertThrowsContains( SQLException.class, @@ -733,6 +740,7 @@ public void various() throws SQLException { } @Test + @SuppressWarnings("try") public void pools() throws SQLException { // ensure all are closed Pools.close(); diff --git a/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java b/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java index 55fd65984..6318745c9 100644 --- a/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/PooledConnectionTest.java @@ -101,30 +101,7 @@ public void testPoolKillConnection() throws Exception { && !"galera".equals(System.getenv("srv")) && !isXpand()); - File tempFile = File.createTempFile("log", ".tmp"); - // - // Logger logger = (Logger) LoggerFactory.getLogger("org.mariadb.jdbc"); - // Level initialLevel = logger.getLevel(); - // logger.setLevel(Level.TRACE); - // logger.setAdditive(false); - // logger.detachAndStopAllAppenders(); - // - // LoggerContext context = new LoggerContext(); - // FileAppender fa = new FileAppender<>(); - // fa.setName("FILE"); - // fa.setImmediateFlush(true); - // PatternLayoutEncoder pa = new PatternLayoutEncoder(); - // pa.setPattern("%r %5p %c [%t] - %m%n"); - // pa.setContext(context); - // pa.start(); - // fa.setEncoder(pa); - // - // fa.setFile(tempFile.getPath()); - // fa.setAppend(true); - // fa.setContext(context); - // fa.start(); - // - // logger.addAppender(fa); + File.createTempFile("log", ".tmp"); try (MariaDbPoolDataSource ds = new MariaDbPoolDataSource(mDefUrl + "&maxPoolSize=1&allowPublicKeyRetrieval")) { @@ -213,7 +190,8 @@ public void testPooledConnectionStatementError() throws Exception { stmt.execute("GRANT SELECT ON " + sharedConn.getCatalog() + ".* TO 'dsUser'@'%'"); } else { stmt.execute( - "CREATE USER 'dsUser'@'%' IDENTIFIED WITH mysql_native_password BY 'MySup8%rPassw@ord'"); + "CREATE USER 'dsUser'@'%' IDENTIFIED WITH mysql_native_password BY" + + " 'MySup8%rPassw@ord'"); stmt.execute("GRANT SELECT ON " + sharedConn.getCatalog() + ".* TO 'dsUser'@'%'"); } } else { diff --git a/src/test/java/org/mariadb/jdbc/integration/PreparedStatementTest.java b/src/test/java/org/mariadb/jdbc/integration/PreparedStatementTest.java index d3b34e970..5db861327 100644 --- a/src/test/java/org/mariadb/jdbc/integration/PreparedStatementTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/PreparedStatementTest.java @@ -701,7 +701,8 @@ private void moreResults(Connection con) throws SQLException { stmt.execute("DROP PROCEDURE IF EXISTS multi"); stmt.setFetchSize(3); stmt.execute( - "CREATE PROCEDURE multi() BEGIN SELECT * from sequence_1_to_10; SELECT * FROM sequence_1_to_10;SELECT 2; END"); + "CREATE PROCEDURE multi() BEGIN SELECT * from sequence_1_to_10; SELECT * FROM" + + " sequence_1_to_10;SELECT 2; END"); stmt.execute("CALL multi()"); Assertions.assertTrue(stmt.getMoreResults()); ResultSet rs = stmt.getResultSet(); @@ -766,7 +767,8 @@ private void moreRowLimitedResults(Connection con) throws SQLException { stmt.setFetchSize(3); stmt.setMaxRows(5); stmt.execute( - "CREATE PROCEDURE multi() BEGIN SELECT * from prepare4; SELECT * FROM prepare4;SELECT 2; END"); + "CREATE PROCEDURE multi() BEGIN SELECT * from prepare4; SELECT * FROM prepare4;SELECT 2;" + + " END"); stmt.execute("CALL multi()"); Assertions.assertTrue(stmt.getMoreResults()); ResultSet rs = stmt.getResultSet(); @@ -922,15 +924,18 @@ public void expectedError() throws SQLException { Common.assertThrowsContains( SQLException.class, () -> prep.executeLargeUpdate("SELECT 1", Statement.NO_GENERATED_KEYS), - "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on" + + " preparedStatement"); Common.assertThrowsContains( SQLException.class, () -> prep.executeLargeUpdate("SELECT 1", new int[] {}), - "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on" + + " preparedStatement"); Common.assertThrowsContains( SQLException.class, () -> prep.executeLargeUpdate("SELECT 1", new String[] {}), - "executeLargeUpdate(String sql, String[] columnNames) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, String[] columnNames) cannot be called on" + + " preparedStatement"); } } @@ -1258,27 +1263,31 @@ public void prepareStmtToString(java.sql.Connection conn, String prefix) throws preparedStatement.setAsciiStream(2, new ByteArrayInputStream("test3".getBytes())); assertEquals( prefix - + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[,]}", + + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[,]}", preparedStatement.toString()); preparedStatement.setObject(1, LocalDateTime.parse("2010-01-12T01:55:12")); preparedStatement.setObject(2, LocalDate.parse("2011-01-01")); assertEquals( prefix - + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:['2010-01-12 01:55:12','2011-01-01']}", + + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:['2010-01-12" + + " 01:55:12','2011-01-01']}", preparedStatement.toString()); preparedStatement.setBigDecimal(1, new BigDecimal("158.9876543210")); preparedStatement.setString(2, "test"); assertEquals( prefix - + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[158.9876543210,'test']}", + + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)'," + + " parameters:[158.9876543210,'test']}", preparedStatement.toString()); preparedStatement.setString(3, "unusedParam"); assertEquals( prefix - + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)', parameters:[158.9876543210,'test','unusedParam']}", + + "{sql:'INSERT INTO prepare1(t1, t2) VALUES (?,?)'," + + " parameters:[158.9876543210,'test','unusedParam']}", preparedStatement.toString()); } } diff --git a/src/test/java/org/mariadb/jdbc/integration/ProcedureParameterTest.java b/src/test/java/org/mariadb/jdbc/integration/ProcedureParameterTest.java index cab2c6eb1..5813cc6ab 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ProcedureParameterTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ProcedureParameterTest.java @@ -103,7 +103,8 @@ public void basicProcedure() throws SQLException { Statement stmt = sharedConn.createStatement(); stmt.execute("DROP PROCEDURE IF EXISTS basic_proc2"); stmt.execute( - "CREATE PROCEDURE basic_proc2 (INOUT t1 INT, IN t2 MEDIUMINT unsigned, OUT t3 DECIMAL(8,3), OUT t4 VARCHAR(20), IN t5 SMALLINT) BEGIN \n" + "CREATE PROCEDURE basic_proc2 (INOUT t1 INT, IN t2 MEDIUMINT unsigned, OUT t3 DECIMAL(8,3)," + + " OUT t4 VARCHAR(20), IN t5 SMALLINT) BEGIN \n" + "set t3 = t1 * t5;\n" + "set t1 = t2 * t1;\n" + "set t4 = 'return data';\n" diff --git a/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java b/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java index e1e555d37..e53c5677b 100644 --- a/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/ProcedureTest.java @@ -9,7 +9,7 @@ import java.io.IOException; import java.io.StringReader; import java.math.BigDecimal; -import java.net.URL; +import java.net.URI; import java.sql.*; import java.util.Calendar; import java.util.HashMap; @@ -122,7 +122,8 @@ public void basicProcedure() throws Throwable { Statement stmt = sharedConn.createStatement(); stmt.execute("DROP PROCEDURE IF EXISTS basic_proc"); stmt.execute( - "CREATE PROCEDURE basic_proc (IN t1 INT, INOUT t2 INT unsigned, OUT t3 INT, IN t4 INT, OUT t5 VARCHAR(20), OUT t6 TIMESTAMP, OUT t7 blob) BEGIN \n" + "CREATE PROCEDURE basic_proc (IN t1 INT, INOUT t2 INT unsigned, OUT t3 INT, IN t4 INT, OUT" + + " t5 VARCHAR(20), OUT t6 TIMESTAMP, OUT t7 blob) BEGIN \n" + "SELECT 1;\n" + "set t3 = t1 * t4;\n" + "set t2 = t2 * t1;\n" @@ -511,7 +512,7 @@ public void setProcedureTest() throws Exception { assertEquals("ab", callableStatement.getString(2)); reset(callableStatement); - callableStatement.setURL(1, new URL("http://a")); + callableStatement.setURL(1, URI.create("http://a").toURL()); callableStatement.setString(2, "b"); callableStatement.execute(); assertEquals("http://ab", callableStatement.getString(2)); @@ -795,7 +796,7 @@ public void setProcedureTest() throws Exception { assertEquals("ab", callableStatement.getString(2)); reset(callableStatement); - callableStatement.setURL("t1", new URL("http://a")); + callableStatement.setURL("t1", URI.create("http://a").toURL()); callableStatement.setString(2, "b"); callableStatement.execute(); assertEquals("http://ab", callableStatement.getString(2)); @@ -1114,12 +1115,14 @@ public void procedureToString() throws SQLException { callableStatement.registerOutParameter(3, JDBCType.INTEGER); callableStatement.registerOutParameter(5, JDBCType.VARCHAR); assertEquals( - "ProcedureStatement{sql:'call basic_proc(?,?,?,?,?,?,?)', parameters:[null,null,null,null,null]}", + "ProcedureStatement{sql:'call basic_proc(?,?,?,?,?,?,?)'," + + " parameters:[null,null,null,null,null]}", callableStatement.toString()); callableStatement.setBytes(2, new byte[] {(byte) 'a', (byte) 'b'}); callableStatement.setLong(1, 10L); assertEquals( - "ProcedureStatement{sql:'call basic_proc(?,?,?,?,?,?,?)', parameters:[10,_binary 'ab',null,null,null]}", + "ProcedureStatement{sql:'call basic_proc(?,?,?,?,?,?,?)', parameters:[10,_binary" + + " 'ab',null,null,null]}", callableStatement.toString()); } } diff --git a/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java b/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java index 67ba65934..8286b5120 100644 --- a/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/Sha256AuthenticationTest.java @@ -76,13 +76,16 @@ public static void init() throws Exception { } stmt.execute( - "CREATE USER 'cachingSha256User'@'%' IDENTIFIED WITH caching_sha2_password BY '!Passw0rd3Works'"); + "CREATE USER 'cachingSha256User'@'%' IDENTIFIED WITH caching_sha2_password BY" + + " '!Passw0rd3Works'"); stmt.execute( "CREATE USER 'cachingSha256User2'@'%' IDENTIFIED WITH caching_sha2_password BY ''"); stmt.execute( - "CREATE USER 'cachingSha256User3'@'%' IDENTIFIED WITH caching_sha2_password BY '!Passw0rd3Works'"); + "CREATE USER 'cachingSha256User3'@'%' IDENTIFIED WITH caching_sha2_password BY" + + " '!Passw0rd3Works'"); stmt.execute( - "CREATE USER 'cachingSha256User4'@'%' IDENTIFIED WITH caching_sha2_password BY '!Passw0rd3Works'"); + "CREATE USER 'cachingSha256User4'@'%' IDENTIFIED WITH caching_sha2_password BY" + + " '!Passw0rd3Works'"); stmt.execute("GRANT ALL PRIVILEGES ON *.* TO 'cachingSha256User'@'%'"); stmt.execute("GRANT ALL PRIVILEGES ON *.* TO 'cachingSha256User2'@'%'"); stmt.execute("GRANT ALL PRIVILEGES ON *.* TO 'cachingSha256User3'@'%'"); diff --git a/src/test/java/org/mariadb/jdbc/integration/SslTest.java b/src/test/java/org/mariadb/jdbc/integration/SslTest.java index ac3d8b6e7..6ac80110a 100644 --- a/src/test/java/org/mariadb/jdbc/integration/SslTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/SslTest.java @@ -326,7 +326,7 @@ public void certificateMandatorySsl() throws Throwable { createCon(baseOptions + "&sslMode=VERIFY_CA&serverSslCert=file:///wrongPath", sslPort)) { assertNotNull(getSslVersion(con)); } catch (Exception e) { - assertTrue(e.getCause() instanceof FileNotFoundException); + assertTrue(e.getCause() instanceof IOException); } if (!"localhost".equals(hostname)) { diff --git a/src/test/java/org/mariadb/jdbc/integration/StatementTest.java b/src/test/java/org/mariadb/jdbc/integration/StatementTest.java index 6a72baf21..b2c31daa2 100644 --- a/src/test/java/org/mariadb/jdbc/integration/StatementTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/StatementTest.java @@ -43,7 +43,8 @@ public static void beforeAll2() throws SQLException { "CREATE TABLE executeGenerated2 (t1 int not null primary key auto_increment, t2 int)"); stmt.execute("CREATE TABLE testAffectedRow(id int)"); stmt.execute( - "CREATE TABLE bigIntId(`id` bigint(20) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, val VARCHAR(256))"); + "CREATE TABLE bigIntId(`id` bigint(20) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, val" + + " VARCHAR(256))"); createSequenceTables(); stmt.execute("FLUSH TABLES"); } @@ -540,8 +541,8 @@ public void queryTimeout() { stmt.setQueryTimeout(1); assertEquals(1, stmt.getQueryTimeout()); stmt.execute( - "select * from information_schema.columns as c1, information_schema.tables, information_schema" - + ".tables as t2"); + "select * from information_schema.columns as c1, information_schema.tables," + + " information_schema.tables as t2"); }, "Query execution was interrupted (max_statement_time exceeded)"); } @@ -632,8 +633,8 @@ public void cancel() throws Exception { () -> { exec.execute(new CancelThread(stmt)); stmt.execute( - "select * from information_schema.columns as c1, information_schema.tables, information_schema" - + ".tables as t2"); + "select * from information_schema.columns as c1, information_schema.tables," + + " information_schema.tables as t2"); exec.shutdown(); }, "Query execution was interrupted"); @@ -875,7 +876,8 @@ public void moreResults() throws SQLException { stmt.execute("DROP PROCEDURE IF EXISTS multi"); stmt.setFetchSize(3); stmt.execute( - "CREATE PROCEDURE multi() BEGIN SELECT * from sequence_1_to_10; SELECT * FROM sequence_1_to_10000;SELECT 2; END"); + "CREATE PROCEDURE multi() BEGIN SELECT * from sequence_1_to_10; SELECT * FROM" + + " sequence_1_to_10000;SELECT 2; END"); stmt.execute("CALL multi()"); assertTrue(stmt.getMoreResults()); ResultSet rs = stmt.getResultSet(); diff --git a/src/test/java/org/mariadb/jdbc/integration/UnixsocketTest.java b/src/test/java/org/mariadb/jdbc/integration/UnixsocketTest.java index ee607938a..32e4eeb5f 100644 --- a/src/test/java/org/mariadb/jdbc/integration/UnixsocketTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/UnixsocketTest.java @@ -20,8 +20,8 @@ static void beforeAllCmd() throws SQLException { sharedConn .createStatement() .execute( - "CREATE TABLE IF NOT EXISTS test_table" - + "(int_column int default 100,mediumtext_column mediumtext null) collate = utf8mb3_bin"); + "CREATE TABLE IF NOT EXISTS test_table(int_column int default 100,mediumtext_column" + + " mediumtext null) collate = utf8mb3_bin"); } @AfterAll @@ -87,10 +87,7 @@ public void testConnectWithUnixSocketWhenDBNotUp() throws IOException { for (int i = 0; i < 10; i++) { assertThrows( - SQLNonTransientConnectionException.class, - () -> { - driver.connect(url, new Properties()); - }); + SQLNonTransientConnectionException.class, () -> driver.connect(url, new Properties())); } proc = rt.exec(commands); stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); diff --git a/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java b/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java index 1501b97da..45d3e517e 100644 --- a/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/UpdateResultSetTest.java @@ -38,15 +38,20 @@ public static void beforeAll2() throws SQLException { org.mariadb.jdbc.Statement stmt = sharedConn.createStatement(); stmt.execute("CREATE TABLE testnoprimarykey(`id` INT NOT NULL,`t1` VARCHAR(50) NOT NULL)"); stmt.execute( - "CREATE TABLE testbasicprimarykey(`id` INT NOT NULL,`t1` VARCHAR(50) NOT NULL, CONSTRAINT pk PRIMARY KEY (id))"); + "CREATE TABLE testbasicprimarykey(`id` INT NOT NULL,`t1` VARCHAR(50) NOT NULL, CONSTRAINT" + + " pk PRIMARY KEY (id))"); stmt.execute( - "CREATE TABLE testMultipleTable1(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50) NULL,PRIMARY KEY (`id1`))"); + "CREATE TABLE testMultipleTable1(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50)" + + " NULL,PRIMARY KEY (`id1`))"); stmt.execute( - "CREATE TABLE testMultipleTable2(`id2` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50) NULL,PRIMARY KEY (`id2`))"); + "CREATE TABLE testMultipleTable2(`id2` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50)" + + " NULL,PRIMARY KEY (`id2`))"); stmt.execute( - "CREATE TABLE testOneNoTable(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50) NULL,PRIMARY KEY (`id1`))"); + "CREATE TABLE testOneNoTable(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50)" + + " NULL,PRIMARY KEY (`id1`))"); stmt.execute( - "CREATE TABLE testAutoIncrement(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50) NULL,PRIMARY KEY (`id1`))"); + "CREATE TABLE testAutoIncrement(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50)" + + " NULL,PRIMARY KEY (`id1`))"); stmt.execute( "CREATE TABLE testUpdateWhenFetch(" @@ -68,7 +73,8 @@ public static void beforeAll2() throws SQLException { + " PRIMARY KEY (`column1`))"); } stmt.execute( - "CREATE TABLE test_update_max(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`t1` VARCHAR(50) NOT NULL)"); + "CREATE TABLE test_update_max(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,`t1` VARCHAR(50)" + + " NOT NULL)"); } /** @@ -91,7 +97,8 @@ public void testNoPrimaryKey() throws Exception { Common.assertThrowsContains( SQLException.class, () -> rs.updateString(1, "1"), - "ResultSet cannot be updated. Cannot update rows, since no primary field is present in query"); + "ResultSet cannot be updated. Cannot update rows, since no primary field is present in" + + " query"); } sharedConn.rollback(); } @@ -112,7 +119,8 @@ public void testBasicPrimaryKey() throws Exception { Common.assertThrowsContains( SQLException.class, () -> rs.updateString(1, "val"), - "ResultSet cannot be updated. Cannot update rows, since primary field id is not present in query"); + "ResultSet cannot be updated. Cannot update rows, since primary field id is not present" + + " in query"); } sharedConn.rollback(); } @@ -219,9 +227,11 @@ public void testMultipleDatabase() throws Exception { stmt.execute("CREATE DATABASE testConnectorJ"); stmt.execute("DROP TABLE IF EXISTS testMultipleDatabase"); stmt.execute( - "CREATE TABLE testMultipleDatabase(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50) NULL,PRIMARY KEY (`id1`))"); + "CREATE TABLE testMultipleDatabase(`id1` INT NOT NULL AUTO_INCREMENT,`t1` VARCHAR(50)" + + " NULL,PRIMARY KEY (`id1`))"); stmt.execute( - "CREATE TABLE testConnectorJ.testMultipleDatabase(`id2` INT NOT NULL AUTO_INCREMENT,`t2` VARCHAR(50) NULL,PRIMARY KEY (`id2`))"); + "CREATE TABLE testConnectorJ.testMultipleDatabase(`id2` INT NOT NULL AUTO_INCREMENT,`t2`" + + " VARCHAR(50) NULL,PRIMARY KEY (`id2`))"); stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER stmt.executeQuery("INSERT INTO testMultipleDatabase(t1) values ('1')"); @@ -269,11 +279,13 @@ public void testMeta() throws Exception { rs.updateString(1, "1-1-bis"); rs.updateRow(); }, - "ResultSet cannot be updated. Cannot update rows, since primary field id is not present in query"); + "ResultSet cannot be updated. Cannot update rows, since primary field id is not present" + + " in query"); Common.assertThrowsContains( SQLException.class, rs::deleteRow, - "ResultSet cannot be updated. Cannot update rows, since primary field id is not present in query"); + "ResultSet cannot be updated. Cannot update rows, since primary field id is not present" + + " in query"); ResultSetMetaData rsmd = rs.getMetaData(); assertFalse(rsmd.isReadOnly(1)); assertFalse(rsmd.isReadOnly(2)); @@ -586,7 +598,8 @@ public void testUpdateChangingMultiplePrimaryKey() throws Exception { + "PRIMARY KEY (`id`,`id2`))"); stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER stmt.execute( - "INSERT INTO testUpdateChangingMultiplePrimaryKey values (1,-1,'1'), (2,-2,'2'), (3,-3,'3')"); + "INSERT INTO testUpdateChangingMultiplePrimaryKey values (1,-1,'1'), (2,-2,'2')," + + " (3,-3,'3')"); try (PreparedStatement preparedStatement = sharedConn.prepareStatement( "SELECT * FROM testUpdateChangingMultiplePrimaryKey", @@ -1081,7 +1094,8 @@ public void repeatedFieldUpdatable() throws SQLException { Statement stmt = sharedConn.createStatement(); stmt.execute("DROP TABLE IF EXISTS repeatedFieldUpdatable"); stmt.execute( - "CREATE TABLE repeatedFieldUpdatable(t1 varchar(50) NOT NULL, t2 varchar(50), PRIMARY KEY (t1))"); + "CREATE TABLE repeatedFieldUpdatable(t1 varchar(50) NOT NULL, t2 varchar(50), PRIMARY KEY" + + " (t1))"); stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER stmt.execute("insert into repeatedFieldUpdatable values ('gg', 'hh'), ('jj', 'll')"); @@ -1173,7 +1187,8 @@ public void addAfterDataFull() throws SQLException { Statement stmt = sharedConn.createStatement(); sharedConn.createStatement().execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER stmt.execute( - "INSERT INTO test_update_max(t1) value ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9'), ('10')"); + "INSERT INTO test_update_max(t1) value ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7')," + + " ('8'), ('9'), ('10')"); try (PreparedStatement preparedStatement = sharedConn.prepareStatement( "SELECT t1, id FROM test_update_max", diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/BinaryCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/BinaryCodecTest.java index fd0a4a315..2f5efccec 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/BinaryCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/BinaryCodecTest.java @@ -37,11 +37,11 @@ public static void beforeAll2() throws SQLException { drop(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE BinaryCodec (t1 VARBINARY(20), t2 VARBINARY(30), t3 VARBINARY(20), t4 BINARY(20)) CHARACTER " - + "SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + "CREATE TABLE BinaryCodec (t1 VARBINARY(20), t2 VARBINARY(30), t3 VARBINARY(20), t4" + + " BINARY(20)) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); stmt.execute( - "INSERT INTO BinaryCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31 23:59:59.152'," - + " '23:54:51.840010', null)"); + "INSERT INTO BinaryCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31" + + " 23:59:59.152', '23:54:51.840010', null)"); stmt.execute( "CREATE TABLE BinaryCodec2 (id int not null primary key auto_increment, t1 VARBINARY(20))"); stmt.execute("FLUSH TABLES"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/CharCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/CharCodecTest.java index 58ec228ea..521706d59 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/CharCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/CharCodecTest.java @@ -39,8 +39,9 @@ public static void beforeAll2() throws SQLException { "CREATE TABLE CharCodec (t1 CHAR(30), t2 CHAR(30), t3 CHAR(25), t4 CHAR(25)) CHARACTER " + "SET utf8mb4 COLLATE utf8mb4_unicode_ci"); stmt.execute( - "INSERT INTO CharCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31 23:59:59.152'," - + " '23:54:51.840010', null),('2010-12-31T23:59:59.152+01:00', '2010-12-31T23:59:59.152Z', null, null)"); + "INSERT INTO CharCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31" + + " 23:59:59.152', '23:54:51.840010', null),('2010-12-31T23:59:59.152+01:00'," + + " '2010-12-31T23:59:59.152Z', null, null)"); stmt.execute("FLUSH TABLES"); } diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/ClobCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/ClobCodecTest.java index 4e42668ce..615320d86 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/ClobCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/ClobCodecTest.java @@ -40,8 +40,8 @@ public static void beforeAll2() throws SQLException { "CREATE TABLE ClobCodec (t1 TINYTEXT, t2 TEXT, t3 MEDIUMTEXT, t4 LONGTEXT) CHARACTER " + "SET utf8mb4 COLLATE utf8mb4_unicode_ci"); stmt.execute( - "INSERT INTO ClobCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31 23:59:59.152'," - + " '23:54:51.840010', null)"); + "INSERT INTO ClobCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31" + + " 23:59:59.152', '23:54:51.840010', null)"); stmt.execute( "CREATE TABLE ClobParamCodec(id int not null primary key auto_increment, t1 TEXT) " + "CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); 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 45cfea382..a6c1d6772 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/DateTimeCodecTest.java @@ -34,10 +34,11 @@ public static void beforeAll2() throws SQLException { drop(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE DateTimeCodec (t1 DATETIME , t2 DATETIME(6), t3 DATETIME(6), t4 DATETIME(6))"); + "CREATE TABLE DateTimeCodec (t1 DATETIME , t2 DATETIME(6), t3 DATETIME(6), t4" + + " DATETIME(6))"); stmt.execute( - "INSERT INTO DateTimeCodec VALUES " - + "('2010-01-12 01:55:12', '1000-01-01 01:55:13.212345', '9999-12-31 18:30:12.55', null)" + "INSERT INTO DateTimeCodec VALUES ('2010-01-12 01:55:12', '1000-01-01 01:55:13.212345'," + + " '9999-12-31 18:30:12.55', null)" + (isMariaDBServer() ? ",('0000-00-00 00:00:00', '0000-00-00 00:00:00', '9999-12-31 00:00:00.00', null)" : "")); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/DecimalCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/DecimalCodecTest.java index d94107fd7..d2eb21bb0 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/DecimalCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/DecimalCodecTest.java @@ -32,15 +32,20 @@ public static void beforeAll2() throws SQLException { drop(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE DecimalCodec (t1 DECIMAL(10,0), t2 DECIMAL(30,6), t3 DECIMAL(10,3), t4 DECIMAL(10,0))"); + "CREATE TABLE DecimalCodec (t1 DECIMAL(10,0), t2 DECIMAL(30,6), t3 DECIMAL(10,3), t4" + + " DECIMAL(10,0))"); stmt.execute( - "CREATE TABLE DecimalCodec2 (t1 DECIMAL(10,0), t2 DECIMAL(10,6), t3 DECIMAL(10,3), t4 DECIMAL(10,0))"); + "CREATE TABLE DecimalCodec2 (t1 DECIMAL(10,0), t2 DECIMAL(10,6), t3 DECIMAL(10,3), t4" + + " DECIMAL(10,0))"); stmt.execute( - "INSERT INTO DecimalCodec VALUES (0, 105.21, -1.6, null), (0, 9223372036854775808, 0, null)"); + "INSERT INTO DecimalCodec VALUES (0, 105.21, -1.6, null), (0, 9223372036854775808, 0," + + " null)"); stmt.execute( - "CREATE TABLE DecimalCodec3 (id int not null primary key auto_increment, t1 DECIMAL(10,0))"); + "CREATE TABLE DecimalCodec3 (id int not null primary key auto_increment, t1" + + " DECIMAL(10,0))"); stmt.execute( - "CREATE TABLE DecimalCodec4 (t1 DECIMAL(10,0) ZEROFILL, t2 DECIMAL(10,6) ZEROFILL, t3 DECIMAL(10,3) ZEROFILL, t4 DECIMAL(10,0) ZEROFILL)"); + "CREATE TABLE DecimalCodec4 (t1 DECIMAL(10,0) ZEROFILL, t2 DECIMAL(10,6) ZEROFILL, t3" + + " DECIMAL(10,3) ZEROFILL, t4 DECIMAL(10,0) ZEROFILL)"); stmt.execute("INSERT INTO DecimalCodec4 VALUES (0, 105.21, 1.6, null)"); stmt.execute("FLUSH TABLES"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/EnumCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/EnumCodecTest.java index 3619ba24d..b6b74a9fa 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/EnumCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/EnumCodecTest.java @@ -38,14 +38,15 @@ public static void beforeAll2() throws SQLException { drop(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE EnumCodec (t1 ENUM('0', '1', 'some🌟', '2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010')," - + " t2 ENUM('0', '1', 'some🌟', '2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010'), " - + " t3 ENUM('0', '1', 'some🌟', '2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010')," - + " t4 ENUM('0', '1', 'some🌟', '2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010'))" - + " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + "CREATE TABLE EnumCodec (t1 ENUM('0', '1', 'some🌟', '2011-01-01', '2010-12-31" + + " 23:59:59.152', '23:54:51.840010'), t2 ENUM('0', '1', 'some🌟', '2011-01-01'," + + " '2010-12-31 23:59:59.152', '23:54:51.840010'), t3 ENUM('0', '1', 'some🌟'," + + " '2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010'), t4 ENUM('0', '1'," + + " 'some🌟', '2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010')) CHARACTER" + + " SET utf8mb4 COLLATE utf8mb4_unicode_ci"); stmt.execute( - "INSERT INTO EnumCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31 23:59:59.152'," - + " '23:54:51.840010', null)"); + "INSERT INTO EnumCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31" + + " 23:59:59.152', '23:54:51.840010', null)"); stmt.execute("CREATE TABLE EnumCodec2 (t1 ENUM('0', '1', '2')) CHARACTER SET binary"); stmt.execute("INSERT INTO EnumCodec2 VALUES ('0'), ('1'), (null)"); stmt.execute("FLUSH TABLES"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/GeometryCollectionCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/GeometryCollectionCodecTest.java index 420629f01..369a84a4f 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/GeometryCollectionCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/GeometryCollectionCodecTest.java @@ -104,15 +104,18 @@ public static void beforeAll2() throws Exception { Assumptions.assumeFalse(isXpand()); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE GeometryCollectionCodec (t1 GeometryCollection, t2 GeometryCollection, t3 GeometryCollection, t4 GeometryCollection)"); + "CREATE TABLE GeometryCollectionCodec (t1 GeometryCollection, t2 GeometryCollection, t3" + + " GeometryCollection, t4 GeometryCollection)"); stmt.execute( - "INSERT INTO GeometryCollectionCodec VALUES " - + "(ST_GeomFromText('GeometryCollection(POINT (0 0), LINESTRING(10 10,20 10,20 20,10 20,10 10))'), " - + "ST_GeomFromText('GeometryCollection(POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10)), MULTIPOINT(0 0,0 10,10 0))'), " - + "ST_GeomFromText('GeometryCollection(MULTILINESTRING((0 0,50 0,50 50,0 50), (10 10,20 10,20 20,10 20)), MULTIPOLYGON(((1 1, 1 8,4 9,6 9,9 3,7 2, 1 1))))'), " - + "null)"); + "INSERT INTO GeometryCollectionCodec VALUES (ST_GeomFromText('GeometryCollection(POINT (0" + + " 0), LINESTRING(10 10,20 10,20 20,10 20,10 10))')," + + " ST_GeomFromText('GeometryCollection(POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20" + + " 10,20 20,10 20,10 10)), MULTIPOINT(0 0,0 10,10 0))')," + + " ST_GeomFromText('GeometryCollection(MULTILINESTRING((0 0,50 0,50 50,0 50), (10" + + " 10,20 10,20 20,10 20)), MULTIPOLYGON(((1 1, 1 8,4 9,6 9,9 3,7 2, 1 1))))'), null)"); stmt.execute( - "CREATE TABLE GeometryCollectionCodec2 (id int not null primary key auto_increment, t1 GeometryCollection)"); + "CREATE TABLE GeometryCollectionCodec2 (id int not null primary key auto_increment, t1" + + " GeometryCollection)"); stmt.execute("FLUSH TABLES"); String binUrl = mDefUrl + (mDefUrl.indexOf("?") > 0 ? "&" : "?") + "geometryDefaultType=default"; @@ -132,7 +135,8 @@ private ResultSet get() throws SQLException { stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER ResultSet rs = stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from GeometryCollectionCodec"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " GeometryCollectionCodec"); assertTrue(rs.next()); sharedConn.commit(); return rs; @@ -143,8 +147,8 @@ private CompleteResult getPrepare(org.mariadb.jdbc.Connection con) throws SQLExc stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER PreparedStatement preparedStatement = con.prepareStatement( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from GeometryCollectionCodec" - + " WHERE 1 > ?"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " GeometryCollectionCodec WHERE 1 > ?"); preparedStatement.closeOnCompletion(); preparedStatement.setInt(1, 0); CompleteResult rs = (CompleteResult) preparedStatement.executeQuery(); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/LineStringCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/LineStringCodecTest.java index c4748d090..b7f9498f8 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/LineStringCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/LineStringCodecTest.java @@ -39,12 +39,15 @@ public static void beforeAll2() throws Exception { Assumptions.assumeFalse(isXpand()); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE LineStringCodec (t1 LineString, t2 LineString, t3 LineString, t4 LineString)"); + "CREATE TABLE LineStringCodec (t1 LineString, t2 LineString, t3 LineString, t4" + + " LineString)"); stmt.execute( - "INSERT INTO LineStringCodec VALUES " - + "( ST_LineStringFromText('LINESTRING(0 0,0 10,10 0)'), ST_LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)'), ST_LineStringFromText('LINESTRING(-1 0.55, 3 5, 1 1)'), null)"); + "INSERT INTO LineStringCodec VALUES ( ST_LineStringFromText('LINESTRING(0 0,0 10,10 0)')," + + " ST_LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')," + + " ST_LineStringFromText('LINESTRING(-1 0.55, 3 5, 1 1)'), null)"); stmt.execute( - "CREATE TABLE LineStringCodec2 (id int not null primary key auto_increment, t1 LineString)"); + "CREATE TABLE LineStringCodec2 (id int not null primary key auto_increment, t1" + + " LineString)"); stmt.execute("FLUSH TABLES"); String binUrl = mDefUrl + (mDefUrl.indexOf("?") > 0 ? "&" : "?") + "geometryDefaultType=default"; @@ -56,7 +59,8 @@ private ResultSet get() throws SQLException { stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER ResultSet rs = stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from LineStringCodec"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " LineStringCodec"); assertTrue(rs.next()); sharedConn.commit(); return rs; diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/LongCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/LongCodecTest.java index af3f02f82..32d6b3088 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/LongCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/LongCodecTest.java @@ -33,8 +33,8 @@ public static void beforeAll2() throws SQLException { Statement stmt = sharedConn.createStatement(); stmt.execute("CREATE TABLE LongCodec (t1 BIGINT, t2 BIGINT, t3 BIGINT, t4 BIGINT)"); stmt.execute( - "CREATE TABLE LongCodecUnsigned (t1 BIGINT UNSIGNED, t2 BIGINT UNSIGNED, t3 BIGINT UNSIGNED, t4 BIGINT " - + "UNSIGNED)"); + "CREATE TABLE LongCodecUnsigned (t1 BIGINT UNSIGNED, t2 BIGINT UNSIGNED, t3 BIGINT" + + " UNSIGNED, t4 BIGINT UNSIGNED)"); stmt.execute("INSERT INTO LongCodec VALUES (0, 1, -1, null)"); stmt.execute("INSERT INTO LongCodecUnsigned VALUES (0, 1, 18446744073709551615, null)"); stmt.execute("CREATE TABLE LongCodec2 (id int not null primary key auto_increment, t1 BIGINT)"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/MediumIntCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/MediumIntCodecTest.java index 6b2651d8e..7368da266 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/MediumIntCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/MediumIntCodecTest.java @@ -35,14 +35,15 @@ public static void beforeAll2() throws SQLException { stmt.execute( "CREATE TABLE MediumIntCodec (t1 MEDIUMINT, t2 MEDIUMINT, t3 MEDIUMINT, t4 MEDIUMINT)"); stmt.execute( - "CREATE TABLE MediumIntCodecUnsigned (t1 MEDIUMINT UNSIGNED, t2 MEDIUMINT UNSIGNED, t3 MEDIUMINT UNSIGNED, t4 MEDIUMINT " - + "UNSIGNED)"); + "CREATE TABLE MediumIntCodecUnsigned (t1 MEDIUMINT UNSIGNED, t2 MEDIUMINT UNSIGNED, t3" + + " MEDIUMINT UNSIGNED, t4 MEDIUMINT UNSIGNED)"); stmt.execute("INSERT INTO MediumIntCodec VALUES (0, 1, -1, null)"); stmt.execute("INSERT INTO MediumIntCodecUnsigned VALUES (0, 1, 16777215, null)"); stmt.execute( "CREATE TABLE MediumIntCodec2 (id int not null primary key auto_increment, t1 MEDIUMINT)"); stmt.execute( - "CREATE TABLE MediumIntCodec3 (id int not null, id2 int not null, t1 MEDIUMINT, PRIMARY KEY (id, id2))"); + "CREATE TABLE MediumIntCodec3 (id int not null, id2 int not null, t1 MEDIUMINT, PRIMARY KEY" + + " (id, id2))"); stmt.execute("FLUSH TABLES"); } diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/MultiLineStringCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/MultiLineStringCodecTest.java index 4f6266bfb..a09d21ead 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/MultiLineStringCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/MultiLineStringCodecTest.java @@ -78,14 +78,16 @@ public static void beforeAll2() throws Exception { Assumptions.assumeFalse(isXpand()); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE MultiLineStringCodec (t1 MultiLineString, t2 MultiLineString, t3 MultiLineString, t4 MultiLineString)"); + "CREATE TABLE MultiLineStringCodec (t1 MultiLineString, t2 MultiLineString, t3" + + " MultiLineString, t4 MultiLineString)"); stmt.execute( - "INSERT INTO MultiLineStringCodec VALUES " - + "(ST_MLineFromText('MULTILINESTRING((1 1,1 5,4 9,6 9,9 3,7 2))'), " - + "ST_MLineFromText('MULTILINESTRING((0 0,50 0,50 50,0 50), (10 10,20 10,20 20,10 20))'), " - + "ST_MLineFromText('MULTILINESTRING((0 0,50 0,50 50,0 50))'), null)"); + "INSERT INTO MultiLineStringCodec VALUES (ST_MLineFromText('MULTILINESTRING((1 1,1 5,4 9,6" + + " 9,9 3,7 2))'), ST_MLineFromText('MULTILINESTRING((0 0,50 0,50 50,0 50), (10 10,20" + + " 10,20 20,10 20))'), ST_MLineFromText('MULTILINESTRING((0 0,50 0,50 50,0 50))')," + + " null)"); stmt.execute( - "CREATE TABLE MultiLineStringCodec2 (id int not null primary key auto_increment, t1 MultiLineString)"); + "CREATE TABLE MultiLineStringCodec2 (id int not null primary key auto_increment, t1" + + " MultiLineString)"); stmt.execute("FLUSH TABLES"); String binUrl = @@ -98,7 +100,8 @@ private ResultSet get() throws SQLException { stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER ResultSet rs = stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from MultiLineStringCodec"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " MultiLineStringCodec"); assertTrue(rs.next()); sharedConn.commit(); return rs; @@ -109,8 +112,8 @@ private CompleteResult getPrepare(org.mariadb.jdbc.Connection con) throws SQLExc stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER PreparedStatement preparedStatement = con.prepareStatement( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from MultiLineStringCodec" - + " WHERE 1 > ?"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " MultiLineStringCodec WHERE 1 > ?"); preparedStatement.closeOnCompletion(); preparedStatement.setInt(1, 0); CompleteResult rs = (CompleteResult) preparedStatement.executeQuery(); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/MultiPointCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/MultiPointCodecTest.java index 3fd242424..116ad1ab0 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/MultiPointCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/MultiPointCodecTest.java @@ -39,12 +39,15 @@ public static void beforeAll2() throws Exception { Assumptions.assumeFalse(isXpand()); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE MultiPointCodec (t1 MultiPoint, t2 MultiPoint, t3 MultiPoint, t4 MultiPoint)"); + "CREATE TABLE MultiPointCodec (t1 MultiPoint, t2 MultiPoint, t3 MultiPoint, t4" + + " MultiPoint)"); stmt.execute( - "INSERT INTO MultiPointCodec VALUES " - + "(ST_MPointFromText('MULTIPOINT(0 0,0 10,10 0)'), ST_MPointFromText('MULTIPOINT(10 10,20 10,20 20,10 20,10 10)'), ST_MPointFromText('MULTIPOINT(-1 0.55, 3 5, 1 1)'), null)"); + "INSERT INTO MultiPointCodec VALUES (ST_MPointFromText('MULTIPOINT(0 0,0 10,10 0)')," + + " ST_MPointFromText('MULTIPOINT(10 10,20 10,20 20,10 20,10 10)')," + + " ST_MPointFromText('MULTIPOINT(-1 0.55, 3 5, 1 1)'), null)"); stmt.execute( - "CREATE TABLE MultiPointCodec2 (id int not null primary key auto_increment, t1 MultiPoint)"); + "CREATE TABLE MultiPointCodec2 (id int not null primary key auto_increment, t1" + + " MultiPoint)"); stmt.execute("FLUSH TABLES"); String binUrl = @@ -57,7 +60,8 @@ private ResultSet get() throws SQLException { stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER ResultSet rs = stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from MultiPointCodec"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " MultiPointCodec"); assertTrue(rs.next()); sharedConn.commit(); return rs; diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/MultiPolygonCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/MultiPolygonCodecTest.java index b24c542fb..b47e54b7a 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/MultiPolygonCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/MultiPolygonCodecTest.java @@ -121,14 +121,17 @@ public static void beforeAll2() throws Exception { Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE MultiPolygonCodec (t1 MultiPolygon, t2 MultiPolygon, t3 MultiPolygon, t4 MultiPolygon)"); + "CREATE TABLE MultiPolygonCodec (t1 MultiPolygon, t2 MultiPolygon, t3 MultiPolygon, t4" + + " MultiPolygon)"); stmt.execute( - "INSERT INTO MultiPolygonCodec VALUES " - + "(ST_MPolyFromText('MULTIPOLYGON(((1 1, 1 5,4 9,6 9,9 3,7 2, 1 1)), ((0 0, 50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10)))'), " - + "ST_MPolyFromText('MULTIPOLYGON(((1 1, 1 8,4 9,6 9,9 3,7 2, 1 1)))'), " - + "ST_MPolyFromText('MULTIPOLYGON(((0 0, 50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10)))'), null)"); + "INSERT INTO MultiPolygonCodec VALUES (ST_MPolyFromText('MULTIPOLYGON(((1 1, 1 5,4 9,6 9,9" + + " 3,7 2, 1 1)), ((0 0, 50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10)))')," + + " ST_MPolyFromText('MULTIPOLYGON(((1 1, 1 8,4 9,6 9,9 3,7 2, 1 1)))')," + + " ST_MPolyFromText('MULTIPOLYGON(((0 0, 50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10" + + " 20,10 10)))'), null)"); stmt.execute( - "CREATE TABLE MultiPolygonCodec2 (id int not null primary key auto_increment, t1 MultiPolygon)"); + "CREATE TABLE MultiPolygonCodec2 (id int not null primary key auto_increment, t1" + + " MultiPolygon)"); stmt.execute("FLUSH TABLES"); String binUrl = @@ -167,7 +170,8 @@ private ResultSet get() throws SQLException { stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER ResultSet rs = stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from MultiPolygonCodec"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " MultiPolygonCodec"); assertTrue(rs.next()); sharedConn.commit(); return rs; @@ -178,8 +182,8 @@ private CompleteResult getPrepare(org.mariadb.jdbc.Connection con) throws SQLExc stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER PreparedStatement preparedStatement = con.prepareStatement( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from MultiPolygonCodec" - + " WHERE 1 > ?"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " MultiPolygonCodec WHERE 1 > ?"); preparedStatement.closeOnCompletion(); preparedStatement.setInt(1, 0); CompleteResult rs = (CompleteResult) preparedStatement.executeQuery(); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/PointCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/PointCodecTest.java index bed80ade0..1f87f41e7 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/PointCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/PointCodecTest.java @@ -38,8 +38,8 @@ public static void beforeAll2() throws Exception { Statement stmt = sharedConn.createStatement(); stmt.execute("CREATE TABLE PointCodec (t1 POINT, t2 POINT, t3 POINT, t4 POINT)"); stmt.execute( - "INSERT INTO PointCodec VALUES " - + "(ST_PointFromText('POINT(10 1)'), ST_PointFromText('POINT(1.5 18)'), ST_PointFromText('POINT(-1 0.55)'), null)"); + "INSERT INTO PointCodec VALUES (ST_PointFromText('POINT(10 1)')," + + " ST_PointFromText('POINT(1.5 18)'), ST_PointFromText('POINT(-1 0.55)'), null)"); stmt.execute("CREATE TABLE PointCodec2 (id int not null primary key auto_increment, t1 POINT)"); stmt.execute("FLUSH TABLES"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/PolygonCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/PolygonCodecTest.java index 7208f41d5..143aafa05 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/PolygonCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/PolygonCodecTest.java @@ -92,10 +92,9 @@ public static void beforeAll2() throws Exception { Statement stmt = sharedConn.createStatement(); stmt.execute("CREATE TABLE PolygonCodec (t1 Polygon, t2 Polygon, t3 Polygon, t4 Polygon)"); stmt.execute( - "INSERT INTO PolygonCodec VALUES " - + "(ST_PolygonFromText('POLYGON((1 1,1 5,4 9,6 9,9 3,7 2,1 1))'), " - + "ST_PolygonFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))'), " - + "ST_PolygonFromText('POLYGON((0 0,50 0,50 50,0 50,0 0))'), null)"); + "INSERT INTO PolygonCodec VALUES (ST_PolygonFromText('POLYGON((1 1,1 5,4 9,6 9,9 3,7 2,1" + + " 1))'), ST_PolygonFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10" + + " 20,10 10))'), ST_PolygonFromText('POLYGON((0 0,50 0,50 50,0 50,0 0))'), null)"); stmt.execute( "CREATE TABLE PolygonCodec2 (id int not null primary key auto_increment, t1 Polygon)"); stmt.execute("FLUSH TABLES"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/SmallIntCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/SmallIntCodecTest.java index 987fdb385..6159d4f92 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/SmallIntCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/SmallIntCodecTest.java @@ -34,8 +34,8 @@ public static void beforeAll2() throws SQLException { stmt.execute( "CREATE TABLE SmallIntCodec2 (id int not null primary key auto_increment, t1 SMALLINT)"); stmt.execute( - "CREATE TABLE SmallIntCodecUnsigned (t1 SMALLINT UNSIGNED, t2 SMALLINT UNSIGNED, t3 SMALLINT UNSIGNED, t4 SMALLINT " - + "UNSIGNED)"); + "CREATE TABLE SmallIntCodecUnsigned (t1 SMALLINT UNSIGNED, t2 SMALLINT UNSIGNED, t3" + + " SMALLINT UNSIGNED, t4 SMALLINT UNSIGNED)"); stmt.execute("INSERT INTO SmallIntCodec VALUES (0, 1, -1, null)"); stmt.execute("INSERT INTO SmallIntCodecUnsigned VALUES (0, 1, 65535, null)"); stmt.execute("FLUSH TABLES"); @@ -96,7 +96,7 @@ public void getObjectPrepared() throws SQLException { } private void getObject(ResultSet rs) throws SQLException { - Object o = rs.getObject(1); + rs.getObject(1); assertEquals(Short.valueOf("0"), rs.getObject(1)); assertFalse(rs.wasNull()); assertEquals(Short.valueOf("1"), rs.getObject(2)); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/TinyIntCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/TinyIntCodecTest.java index 6314870fc..86a2dc359 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/TinyIntCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/TinyIntCodecTest.java @@ -35,8 +35,8 @@ public static void beforeAll2() throws SQLException { stmt.execute( "CREATE TABLE TinyIntCodec2 (id int not null primary key auto_increment, t1 TINYINT)"); stmt.execute( - "CREATE TABLE TinyIntCodecUnsigned (t1 TINYINT UNSIGNED, t2 TINYINT UNSIGNED, t3 TINYINT UNSIGNED, t4 TINYINT " - + "UNSIGNED)"); + "CREATE TABLE TinyIntCodecUnsigned (t1 TINYINT UNSIGNED, t2 TINYINT UNSIGNED, t3 TINYINT" + + " UNSIGNED, t4 TINYINT UNSIGNED)"); stmt.execute("INSERT INTO TinyIntCodec VALUES (0, 1, -1, null)"); stmt.execute("INSERT INTO TinyIntCodecUnsigned VALUES (0, 1, 255, null)"); stmt.execute("FLUSH TABLES"); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/UuidCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/UuidCodecTest.java index 18f50d1a4..9c51ab78d 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/UuidCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/UuidCodecTest.java @@ -40,7 +40,9 @@ && minVersion(10, 7, 0) stmt.execute("CREATE TABLE UuidCodec (t1 UUID, t2 UUID, t3 UUID, t4 UUID)"); stmt.execute("CREATE TABLE UuidCodec2 (t1 UUID)"); stmt.execute( - "INSERT INTO UuidCodec VALUES ('123e4567-e89b-12d3-a456-426655440000', '93aac041-1a14-11ec-ab4e-f859713e4be4', 'ffffffff-ffff-ffff-ffff-fffffffffffe', null)"); + "INSERT INTO UuidCodec VALUES ('123e4567-e89b-12d3-a456-426655440000'," + + " '93aac041-1a14-11ec-ab4e-f859713e4be4', 'ffffffff-ffff-ffff-ffff-fffffffffffe'," + + " null)"); } private ResultSet get() throws SQLException { @@ -55,20 +57,6 @@ private ResultSet get() throws SQLException { return rs; } - private ResultSet getAdd(String additional) throws SQLException { - try (Connection con = createCon(additional)) { - java.sql.Statement stmt = con.createStatement(); - stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER - stmt.closeOnCompletion(); - ResultSet rs = - stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from UuidCodec"); - assertTrue(rs.next()); - con.commit(); - return rs; - } - } - private ResultSet getPrepare(Connection con) throws SQLException { java.sql.Statement stmt = con.createStatement(); stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER @@ -349,7 +337,17 @@ public void getMetaData() throws SQLException { assertEquals("", meta.getSchemaName(1)); assertEquals(36, meta.getColumnDisplaySize(1)); - rs = getAdd("&uuidAsString=True"); + try (Connection con = createCon("&uuidAsString=True")) { + java.sql.Statement stmt = con.createStatement(); + stmt.execute("START TRANSACTION"); // if MAXSCALE ensure using WRITER + stmt.closeOnCompletion(); + rs = + stmt.executeQuery( + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from UuidCodec"); + assertTrue(rs.next()); + con.commit(); + } + meta = rs.getMetaData(); assertEquals("uuid", meta.getColumnTypeName(1)); assertEquals(sharedConn.getCatalog(), meta.getCatalogName(1)); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/VarbinaryCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/VarbinaryCodecTest.java index a76b05d84..f244ac71e 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/VarbinaryCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/VarbinaryCodecTest.java @@ -34,11 +34,12 @@ public static void beforeAll2() throws SQLException { drop(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE VarbinaryCodec (t1 VARBINARY(20), t2 VARBINARY(30), t3 VARBINARY(20), t4 VARBINARY(20))"); + "CREATE TABLE VarbinaryCodec (t1 VARBINARY(20), t2 VARBINARY(30), t3 VARBINARY(20), t4" + + " VARBINARY(20))"); stmt.execute("CREATE TABLE VarbinaryCodec2 (t1 VARBINARY(20))"); stmt.execute( - "INSERT INTO VarbinaryCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31 23:59:59.152'," - + " '23:54:51.840010', null)"); + "INSERT INTO VarbinaryCodec VALUES ('0', '1', 'some🌟', null), ('2011-01-01', '2010-12-31" + + " 23:59:59.152', '23:54:51.840010', null)"); } private ResultSet get() throws SQLException { @@ -47,7 +48,8 @@ private ResultSet get() throws SQLException { stmt.closeOnCompletion(); ResultSet rs = stmt.executeQuery( - "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from VarbinaryCodec"); + "select t1 as t1alias, t2 as t2alias, t3 as t3alias, t4 as t4alias from" + + " VarbinaryCodec"); assertTrue(rs.next()); sharedConn.commit(); return rs; diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/VarcharCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/VarcharCodecTest.java index 0f1fda4cc..14b0f776b 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/VarcharCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/VarcharCodecTest.java @@ -40,8 +40,8 @@ public static void beforeAll2() throws SQLException { after2(); Statement stmt = sharedConn.createStatement(); stmt.execute( - "CREATE TABLE StringCodec (t1 VARCHAR(255), t2 VARCHAR(30), t3 VARCHAR(20), t4 VARCHAR(20)) CHARACTER " - + "SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + "CREATE TABLE StringCodec (t1 VARCHAR(255), t2 VARCHAR(30), t3 VARCHAR(20), t4 VARCHAR(20))" + + " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); stmt.execute( "INSERT INTO StringCodec VALUES ('0', '1', 'some🌟', null), " + "('2011-01-01', '2010-12-31 23:59:59.152', '23:54:51.840010', null), " @@ -51,7 +51,8 @@ public static void beforeAll2() throws SQLException { "CREATE TABLE StringParamCodec(id int not null primary key auto_increment, t1 VARCHAR(20)) " + "CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); stmt.execute( - "CREATE TABLE StringCodecWrong (t1 VARCHAR(20)) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + "CREATE TABLE StringCodecWrong (t1 VARCHAR(20)) CHARACTER SET utf8mb4 COLLATE" + + " utf8mb4_unicode_ci"); stmt.execute("FLUSH TABLES"); } @@ -1057,7 +1058,7 @@ private void sendParam(Connection con) throws SQLException { @Test public void wrongUtf8String() throws SQLException { final byte[] utf8WrongBytes = - new byte[] {(byte) 0xc2, (byte) 0f, (byte) 0xDB, (byte) 0, (byte) 0xE1, (byte) 0}; + new byte[] {(byte) 0xc2, (byte) 0x0f, (byte) 0xDB, (byte) 0x00, (byte) 0xE1, (byte) 0x00}; String st = new String(utf8WrongBytes); wrongUtf8(sharedConn, st); diff --git a/src/test/java/org/mariadb/jdbc/integration/codec/YearCodecTest.java b/src/test/java/org/mariadb/jdbc/integration/codec/YearCodecTest.java index 6fe4b6b23..2a7002958 100644 --- a/src/test/java/org/mariadb/jdbc/integration/codec/YearCodecTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/codec/YearCodecTest.java @@ -33,11 +33,13 @@ public static void beforeAll2() throws SQLException { if (isMariaDBServer() && !isXpand()) { stmt.execute("CREATE TABLE YearCodec (t1 YEAR(2), t2 YEAR(4), t3 YEAR(4), t4 YEAR(4))"); stmt.execute( - "INSERT INTO YearCodec VALUES ('2010', '1901', '2155', null), (80, '1901', '2155', null)"); + "INSERT INTO YearCodec VALUES ('2010', '1901', '2155', null), (80, '1901', '2155'," + + " null)"); } else { stmt.execute("CREATE TABLE YearCodec (t1 YEAR(4), t2 YEAR(4), t3 YEAR(4), t4 YEAR(4))"); stmt.execute( - "INSERT INTO YearCodec VALUES ('2010', '1901', '2155', null), (1980, '1901', '2155', null)"); + "INSERT INTO YearCodec VALUES ('2010', '1901', '2155', null), (1980, '1901', '2155'," + + " null)"); } stmt.execute("FLUSH TABLES"); } diff --git a/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java b/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java index 5e37f72b8..5f923ebc2 100644 --- a/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java @@ -33,8 +33,8 @@ public static void beforeAll2() throws SQLException { stmt.execute("CREATE TABLE ResultSetTest (t1 int not null primary key auto_increment, t2 int)"); stmt.execute("INSERT INTO ResultSetTest(t2) values (1),(2),(3),(4),(5),(6),(7),(8)"); stmt.execute( - "CREATE TABLE test_rsmd(id_col int not null primary key auto_increment, " - + "nullable_col varchar(20), unikey_col int unique, char_col char(10), us smallint unsigned)"); + "CREATE TABLE test_rsmd(id_col int not null primary key auto_increment, nullable_col" + + " varchar(20), unikey_col int unique, char_col char(10), us smallint unsigned)"); stmt.execute("CREATE TABLE resultsetmetadatatest1(id int, name varchar(20))"); stmt.execute("CREATE TABLE resultsetmetadatatest2(id int, name varchar(20))"); stmt.execute("CREATE TABLE resultsetmetadatatest3(id int, name varchar(20))"); @@ -127,7 +127,8 @@ public void conj84() throws Exception { sharedConn .createStatement() .executeQuery( - "select resultsetmetadatatest1.*, resultsetmetadatatest2.* FROM resultsetmetadatatest1 join resultsetmetadatatest2"); + "select resultsetmetadatatest1.*, resultsetmetadatatest2.* FROM" + + " resultsetmetadatatest1 join resultsetmetadatatest2"); assertTrue(rs.next()); assertEquals(rs.findColumn("id"), 1); assertEquals(rs.findColumn("name"), 2); @@ -198,7 +199,8 @@ public void blankTableNameMeta() throws Exception { sharedConn .createStatement() .executeQuery( - "SELECT id AS id_alias FROM resultsetmetadatatest3 AS resultsetmetadatatest1_alias"); + "SELECT id AS id_alias FROM resultsetmetadatatest3 AS" + + " resultsetmetadatatest1_alias"); ResultSetMetaData rsmd = rs.getMetaData(); assertEquals("resultsetmetadatatest3", rsmd.getTableName(1)); @@ -210,7 +212,8 @@ public void blankTableNameMeta() throws Exception { connection .createStatement() .executeQuery( - "SELECT id AS id_alias FROM resultsetmetadatatest3 AS resultsetmetadatatest1_alias"); + "SELECT id AS id_alias FROM resultsetmetadatatest3 AS" + + " resultsetmetadatatest1_alias"); rsmd = rs.getMetaData(); assertEquals("", rsmd.getTableName(1)); diff --git a/src/test/java/org/mariadb/jdbc/unit/client/HostnameVerifierTest.java b/src/test/java/org/mariadb/jdbc/unit/client/HostnameVerifierTest.java index 50d943caa..e75c1a437 100644 --- a/src/test/java/org/mariadb/jdbc/unit/client/HostnameVerifierTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/client/HostnameVerifierTest.java @@ -46,8 +46,7 @@ public void verifyCn() throws Exception { // CN=test.com X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIC+zCCAeOgAwIBAgIJANin/585wAXHMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV\n" + "BAMMCHRlc3QuY29tMCAXDTE3MDYyMzEzNTI1NloYDzIxMTcwNTMwMTM1MjU2WjAT\n" + "MREwDwYDVQQDDAh0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" @@ -81,8 +80,7 @@ public void verifyNoSan() throws Exception { // CN=*.mariadb.com X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDLjCCAhYCFEWSUFTlr/qGo/jC5R1nNQdE5zmrMA0GCSqGSIb3DQEBCwUAMFIx\n" + "CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJHRDELMAkGA1UEBwwCU1oxEjAQBgNVBAoM\n" + "CUFjbWUsSW5jLjEVMBMGA1UEAwwMQWNtZSBSb290IENBMCAXDTIxMDMzMDA5MjQ1\n" @@ -114,8 +112,7 @@ public void verifyNonAsciiCn() throws Exception { // CN=😎.com = "\uD83D\uDE0E" X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDWTCCAkGgAwIBAgIJAI38v686DwcOMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNV\n" + "BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UECgwKQWNtZSwgSW5jLjERMA8GA1UE\n" + "AwwI8J+Yji5jb20wIBcNMTcwNjIzMTQyNzQ2WhgPMjExNzA1MzAxNDI3NDZaMEIx\n" @@ -155,8 +152,7 @@ public void verifySubjectAlt() throws Exception { // -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDUzCCAjugAwIBAgIJAPMG38xrY9DcMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV\n" + "BAYTAkNOMQswCQYDVQQIDAJHRDELMAkGA1UEBwwCU1oxEzARBgNVBAoMCkFjbWUs\n" + "IEluYy4xFTATBgNVBAMMDEFjbWUgUm9vdCBDQTAgFw0xNzA2MjMxNjEyNTlaGA8y\n" @@ -202,8 +198,7 @@ public void verifySubjectAltOnly() throws Exception { // subjectAlt=foo.com X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIESjCCAzKgAwIBAgIJAIz+EYMBU6aYMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" + "VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" + "ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" @@ -232,9 +227,9 @@ public void verifySubjectAltOnly() throws Exception { verifyExceptionEqual( "a.foo.com", cert, - "CN not found in certificate principal " - + "\"EMAILADDRESS=juliusdavies@gmail.com, OU=test certificates, O=httpcomponents, L=Forest Hill, " - + "ST=Maryland, C=US\" and DNS host \"a.foo.com\" doesn't correspond to SAN[{DNS:\"foo.com\"}]"); + "CN not found in certificate principal \"EMAILADDRESS=juliusdavies@gmail.com, OU=test" + + " certificates, O=httpcomponents, L=Forest Hill, ST=Maryland, C=US\" and DNS host" + + " \"a.foo.com\" doesn't correspond to SAN[{DNS:\"foo.com\"}]"); } @Test @@ -266,7 +261,8 @@ public void noCn() throws Exception { verifyExceptionEqual( "a.foo.com", cert, - "CN not found in certificate principal \"O=Internet Widgits Pty Ltd, ST=Some-State, C=AU\" and certificate doesn't contain SAN"); + "CN not found in certificate principal \"O=Internet Widgits Pty Ltd, ST=Some-State, C=AU\"" + + " and certificate doesn't contain SAN"); } @Test @@ -274,8 +270,7 @@ public void verifyMultipleCn() throws Exception { // CN=test1.org, CN=test2.org X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDgzCCAmugAwIBAgIJAPqfD+J8D4gqMA0GCSqGSIb3DQEBBQUAMFcxCzAJBgNV\n" + "BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UECgwKQWNtZSwgSW5jLjESMBAGA1UE\n" + "AwwJdGVzdDEub3JnMRIwEAYDVQQDDAl0ZXN0Mi5vcmcwIBcNMTcwNjIzMTYxNDIx\n" @@ -308,8 +303,7 @@ public void verifyWilcardCn() throws Exception { // CN=*.foo.com X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIESDCCAzCgAwIBAgIJAIz+EYMBU6aUMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" + "VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" + "ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" @@ -350,8 +344,7 @@ public void verifyWilcardCnOnTld() throws Exception { // CN=*.co.jp X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aVMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" + "VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" + "ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" @@ -386,8 +379,7 @@ public void subjectAltUsesLocalDomainAndIp() throws Exception { // subjectAltName=DNS:localhost.localdomain,DNS:localhost,IP:127.0.0.1 X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDfDCCAmSgAwIBAgIURZJQVOWv+oaj+MLlHWc1B0TnOaowDQYJKoZIhvcNAQEL\n" + "BQAwUjELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjESMBAG\n" + "A1UECgwJQWNtZSxJbmMuMRUwEwYDVQQDDAxBY21lIFJvb3QgQ0EwIBcNMjEwMzMw\n" @@ -417,22 +409,22 @@ public void subjectAltUsesLocalDomainAndIp() throws Exception { verifyExceptionEqual( "local.host", cert, - "DNS host \"local.host\" doesn't correspond to certificate " - + "CN \"*.mariadb.org\" and SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); + "DNS host \"local.host\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); HostnameVerifier.verify("127.0.0.1", cert, -1); verifyExceptionEqual( "127.0.0.2", cert, - "IPv4 host \"127.0.0.2\" doesn't correspond to certificate " - + "CN \"*.mariadb.org\" and SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); + "IPv4 host \"127.0.0.2\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); HostnameVerifier.verify("2001:db8:3902:3468:0:0:0:443", cert, -1); verifyExceptionEqual( "2001:db8:1::", cert, - "IPv6 host \"2001:db8:1::\" doesn't correspond to certificate " - + "CN \"*.mariadb.org\" and SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); + "IPv6 host \"2001:db8:1::\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"localhost.localdomain\"},{DNS:\"localhost\"},{IP:\"127.0.0.1\"},{IP:\"2001:db8:3902:3468:0:0:0:443\"}]"); } @Test @@ -440,8 +432,7 @@ public void wildcardsCannotMatchIpAddresses() throws Exception { // openssl req -x509 -nodes -days 36500 -subj '/CN=*.0.0.1' -newkey rsa:512 -out cert.pem X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDVzCCAj+gAwIBAgIJAN9L/Y9e1F7dMA0GCSqGSIb3DQEBBQUAMEExCzAJBgNV\n" + "BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UECgwKQWNtZSwgSW5jLjEQMA4GA1UE\n" + "AwwHKi4wLjAuMTAgFw0xNzA2MjMxNTU3MTdaGA8yMTE3MDUzMDE1NTcxN1owQTEL\n" @@ -473,8 +464,7 @@ public void subjectAltNameWithWildcard() throws Exception { // subjectAltName=DNS:*.other.org,DNS:a*b.other2.com X509Certificate cert = getCertificate( - "" - + "-----BEGIN CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDVjCCAj6gAwIBAgIJAPMG38xrY9DaMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV\n" + "BAYTAkNOMQswCQYDVQQIDAJHRDELMAkGA1UEBwwCU1oxEzARBgNVBAoMCkFjbWUs\n" + "IEluYy4xFTATBgNVBAMMDEFjbWUgUm9vdCBDQTAgFw0xNzA2MjMxNjA1MTlaGA8y\n" @@ -498,35 +488,35 @@ public void subjectAltNameWithWildcard() throws Exception { verifyExceptionEqual( "other.org", cert, - "DNS host \"other.org\" doesn't correspond " - + "to certificate CN \"*.mariadb.org\" and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); + "DNS host \"other.org\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); HostnameVerifier.verify("www.other.org", cert, -1); verifyExceptionEqual( "other2.org", cert, - "DNS host \"other2.org\" doesn't correspond " - + "to certificate CN \"*.mariadb.org\" and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); + "DNS host \"other2.org\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); verifyExceptionEqual( "www.other2.org", cert, - "DNS host \"www.other2.org\" doesn't correspond " - + "to certificate CN \"*.mariadb.org\" and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); + "DNS host \"www.other2.org\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); HostnameVerifier.verify("ab.other2.com", cert, -1); HostnameVerifier.verify("axxxxb.other2.com", cert, -1); verifyExceptionEqual( "axxxxbc.other2.org", cert, - "DNS host \"axxxxbc.other2.org\" doesn't " - + "correspond to certificate CN \"*.mariadb.org\" and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); + "DNS host \"axxxxbc.other2.org\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); verifyExceptionEqual( "caxxxxb.other2.org", cert, - "DNS host \"caxxxxb.other2.org\" doesn't " - + "correspond to certificate CN \"*.mariadb.org\" and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); + "DNS host \"caxxxxb.other2.org\" doesn't correspond to certificate CN \"*.mariadb.org\" and" + + " SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); verifyExceptionEqual( "a.axxxxb.other2.org", cert, - "DNS host \"a.axxxxb.other2.org\" doesn't " - + "correspond to certificate CN \"*.mariadb.org\" and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); + "DNS host \"a.axxxxb.other2.org\" doesn't correspond to certificate CN \"*.mariadb.org\"" + + " and SAN[{DNS:\"*.other.org\"},{DNS:\"a*b.other2.com\"}]"); } } diff --git a/src/test/java/org/mariadb/jdbc/unit/client/socket/PacketWriterTest.java b/src/test/java/org/mariadb/jdbc/unit/client/socket/PacketWriterTest.java index 0b86e166d..cfa91b87d 100644 --- a/src/test/java/org/mariadb/jdbc/unit/client/socket/PacketWriterTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/client/socket/PacketWriterTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.unit.client.socket; import java.io.IOException; diff --git a/src/test/java/org/mariadb/jdbc/unit/export/HaModeTest.java b/src/test/java/org/mariadb/jdbc/unit/export/HaModeTest.java index b4bb8d3b1..f46bf63b8 100644 --- a/src/test/java/org/mariadb/jdbc/unit/export/HaModeTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/export/HaModeTest.java @@ -1,7 +1,6 @@ -// SPDX-License-Identifier: LGPL-2.1-or-later -// Copyright (c) 2012-2014 Monty Program Ab -// Copyright (c) 2023 MariaDB Corporation Ab - +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.unit.export; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -33,14 +32,16 @@ private void getAvailableHostWithoutConnectionNumber(HaMode haMode) { ConcurrentMap denyList = new ConcurrentHashMap<>(); HostCounter hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, true).get(), false); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, true); + if (availHost.isPresent()) hostCounter.add(availHost.get(), false); } assertEquals("prim1:34,prim2:33,prim3:33", hostCounter.results()); haMode.resetLast(); hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, false).get(), false); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, false); + if (availHost.isPresent()) hostCounter.add(availHost.get(), false); } assertEquals("slave1:34,slave2:33,slave3:33", hostCounter.results()); @@ -50,7 +51,8 @@ private void getAvailableHostWithoutConnectionNumber(HaMode haMode) { hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, true).get(), false); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, true); + if (availHost.isPresent()) hostCounter.add(availHost.get(), false); } assertEquals("prim1:50,prim3:50", hostCounter.results()); @@ -60,7 +62,8 @@ private void getAvailableHostWithoutConnectionNumber(HaMode haMode) { denyList.put(hostAddresses.get(4), System.currentTimeMillis() + 1000); hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, false).get(), false); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, false); + if (availHost.isPresent()) hostCounter.add(availHost.get(), false); } assertEquals("slave1:50,slave3:50", hostCounter.results()); } @@ -96,7 +99,8 @@ private void getAvailableHostWithConnectionNumber(HaMode haMode) { ConcurrentMap denyList = new ConcurrentHashMap<>(); HostCounter hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, true).get(), true); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, true); + if (availHost.isPresent()) hostCounter.add(availHost.get(), true); } assertEquals("prim2:25,prim3:75", hostCounter.results()); @@ -105,7 +109,8 @@ private void getAvailableHostWithConnectionNumber(HaMode haMode) { host3.setThreadsConnected(100); hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, true).get(), true); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, true); + if (availHost.isPresent()) hostCounter.add(availHost.get(), true); } assertEquals("prim1:34,prim2:33,prim3:33", hostCounter.results()); @@ -114,7 +119,8 @@ private void getAvailableHostWithConnectionNumber(HaMode haMode) { slave3.setThreadsConnected(100); hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, false).get(), true); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, false); + if (availHost.isPresent()) hostCounter.add(availHost.get(), true); } assertEquals("slave2:25,slave3:75", hostCounter.results()); @@ -125,7 +131,8 @@ private void getAvailableHostWithConnectionNumber(HaMode haMode) { host3.setThreadsConnected(100); hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, true).get(), true); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, true); + if (availHost.isPresent()) hostCounter.add(availHost.get(), true); } assertEquals("prim1:25,prim3:75", hostCounter.results()); @@ -137,12 +144,13 @@ private void getAvailableHostWithConnectionNumber(HaMode haMode) { slave3.setThreadsConnected(100); hostCounter = new HostCounter(); for (int i = 0; i < 100; i++) { - hostCounter.add(haMode.getAvailableHost(hostAddresses, denyList, false).get(), true); + Optional availHost = haMode.getAvailableHost(hostAddresses, denyList, false); + if (availHost.isPresent()) hostCounter.add(availHost.get(), true); } assertEquals("slave1:25,slave3:75", hostCounter.results()); } - private class HostCounter { + private static class HostCounter { Map hosts = new HashMap<>(); public void add(HostAddress hostAddress, boolean increment) { 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 7af945e12..ade5a6f18 100644 --- a/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java @@ -488,7 +488,8 @@ public void testJdbcParserBooleanOption() { assertTrue( sqle.getMessage() .contains( - "Optional parameter autoReconnect must be boolean (true/false or 0/1) was \"truee\"")); + "Optional parameter autoReconnect must be boolean (true/false or 0/1) was" + + " \"truee\"")); } } @@ -552,8 +553,8 @@ public void testJdbcParserParameter() throws SQLException { assertEquals(HostAddress.from("master3", 3308, true), conf.addresses().get(2)); url = - "jdbc:mariadb:replication://address=(port=3306)(host=master1),address=(port=3307)" - + "(host=slave1) ,address=(host=slave2)(port=3308)(other=5/database?user=greg&password=pass"; + "jdbc:mariadb:replication://address=(port=3306)(host=master1),address=(port=3307)(host=slave1)" + + " ,address=(host=slave2)(port=3308)(other=5/database?user=greg&password=pass"; conf = org.mariadb.jdbc.Configuration.parse(url); assertEquals("database", conf.database()); assertEquals("greg", conf.user()); @@ -849,7 +850,8 @@ public void builder() throws SQLException { .useCatalogTerm("schema") .build(); assertEquals( - "jdbc:mariadb://host1:3305,address=(host=host2)(port=3307)(type=replica)/db?user=me&password=***&timezone=UTC&autocommit=false&useCatalogTerm=UseSchema&createDatabaseIfNotExist=true&useLocalSessionState=true&transactionIsolation=REPEATABLE_READ&defaultFetchSize=10&maxQuerySizeToLog=100&maxAllowedPacket=8000&geometryDefaultType=default&restrictedAuth=mysql_native_password,client_ed25519&initSql=SET @@a='10'&socketFactory=someSocketFactory&connectTimeout=22&pipe=pipeName&localSocket=localSocket&uuidAsString=true&tcpKeepAlive=false&tcpKeepIdle=10&tcpKeepCount=50&tcpKeepInterval=50&tcpAbortiveClose=true&localSocketAddress=localSocketAddress&socketTimeout=1000&useReadAheadInput=true&tlsSocketType=TLStype&sslMode=TRUST&serverSslCert=mycertPath&keyStore=/tmp&keyStorePassword=MyPWD&keyStoreType=JKS&trustStoreType=JKS&enabledSslCipherSuites=myCipher,cipher2&enabledSslProtocolSuites=TLSv1.2&allowMultiQueries=true&allowLocalInfile=false&useCompression=true&useAffectedRows=true&disablePipeline=true&cachePrepStmts=false&prepStmtCacheSize=2&useServerPrepStmts=true&credentialType=ENV&sessionVariables=blabla&connectionAttributes=bla=bla&servicePrincipalName=SPN&blankTableNameMeta=true&tinyInt1isBit=false&yearIsDateType=false&dumpQueriesOnException=true&includeInnodbStatusInDeadlockExceptions=true&includeThreadDumpInDeadlockExceptions=true&retriesAllDown=10&galeraAllowedState=A,B&transactionReplay=true&pool=true&poolName=myPool&maxPoolSize=16&minPoolSize=12&maxIdleTime=25000®isterJmxPool=false&poolValidMinDelay=260&useResetConnection=true&serverRsaPublicKeyFile=RSAPath&allowPublicKeyRetrieval=true", + "jdbc:mariadb://host1:3305,address=(host=host2)(port=3307)(type=replica)/db?user=me&password=***&timezone=UTC&autocommit=false&useCatalogTerm=UseSchema&createDatabaseIfNotExist=true&useLocalSessionState=true&transactionIsolation=REPEATABLE_READ&defaultFetchSize=10&maxQuerySizeToLog=100&maxAllowedPacket=8000&geometryDefaultType=default&restrictedAuth=mysql_native_password,client_ed25519&initSql=SET" + + " @@a='10'&socketFactory=someSocketFactory&connectTimeout=22&pipe=pipeName&localSocket=localSocket&uuidAsString=true&tcpKeepAlive=false&tcpKeepIdle=10&tcpKeepCount=50&tcpKeepInterval=50&tcpAbortiveClose=true&localSocketAddress=localSocketAddress&socketTimeout=1000&useReadAheadInput=true&tlsSocketType=TLStype&sslMode=TRUST&serverSslCert=mycertPath&keyStore=/tmp&keyStorePassword=MyPWD&keyStoreType=JKS&trustStoreType=JKS&enabledSslCipherSuites=myCipher,cipher2&enabledSslProtocolSuites=TLSv1.2&allowMultiQueries=true&allowLocalInfile=false&useCompression=true&useAffectedRows=true&disablePipeline=true&cachePrepStmts=false&prepStmtCacheSize=2&useServerPrepStmts=true&credentialType=ENV&sessionVariables=blabla&connectionAttributes=bla=bla&servicePrincipalName=SPN&blankTableNameMeta=true&tinyInt1isBit=false&yearIsDateType=false&dumpQueriesOnException=true&includeInnodbStatusInDeadlockExceptions=true&includeThreadDumpInDeadlockExceptions=true&retriesAllDown=10&galeraAllowedState=A,B&transactionReplay=true&pool=true&poolName=myPool&maxPoolSize=16&minPoolSize=12&maxIdleTime=25000®isterJmxPool=false&poolValidMinDelay=260&useResetConnection=true&serverRsaPublicKeyFile=RSAPath&allowPublicKeyRetrieval=true", conf.toString()); } @@ -919,13 +921,15 @@ public void toConf() throws SQLException { "jdbc:mariadb:loadbalance://host1:3305,address=(host=host2)(port=3307)(type=replica)/db?nonExisting&nonExistingWithValue=tt&user=me&password=***&timezone=UTC&autocommit=false&createDatabaseIfNotExist=true&") .startsWith( "Configuration:\n" - + " * resulting Url : jdbc:mariadb:loadbalance://address=(host=host1)(port=3305)(type=primary),address=(host=host2)(port=3307)(type=replica)/db?user=me&password=***&nonExisting=&nonExistingWithValue=tt&timezone=UTC&autocommit=false&createDatabaseIfNotExist=true\n" + + " * resulting Url :" + + " jdbc:mariadb:loadbalance://address=(host=host1)(port=3305)(type=primary),address=(host=host2)(port=3307)(type=replica)/db?user=me&password=***&nonExisting=&nonExistingWithValue=tt&timezone=UTC&autocommit=false&createDatabaseIfNotExist=true\n" + "Unknown options : \n" + " * nonExisting : \n" + " * nonExistingWithValue : tt\n" + "\n" + "Non default options : \n" - + " * addresses : [address=(host=host1)(port=3305)(type=primary), address=(host=host2)(port=3307)(type=replica)]\n" + + " * addresses : [address=(host=host1)(port=3305)(type=primary)," + + " address=(host=host2)(port=3307)(type=replica)]\n" + " * autocommit : false\n" + " * createDatabaseIfNotExist : true\n" + " * database : db\n" @@ -944,7 +948,8 @@ public void toConf() throws SQLException { "jdbc:mariadb://localhost/test?user=root&sslMode=verify-ca&serverSslCert=/tmp/t.pem&trustStoreType=JKS&keyStore=/tmp/keystore&keyStorePassword=kspass") .startsWith( "Configuration:\n" - + " * resulting Url : jdbc:mariadb://localhost/test?user=root&sslMode=VERIFY_CA&serverSslCert=/tmp/t.pem&keyStore=/tmp/keystore&keyStorePassword=kspass&trustStoreType=JKS\n" + + " * resulting Url :" + + " jdbc:mariadb://localhost/test?user=root&sslMode=VERIFY_CA&serverSslCert=/tmp/t.pem&keyStore=/tmp/keystore&keyStorePassword=kspass&trustStoreType=JKS\n" + "Unknown options : None\n" + "\n" + "Non default options : \n" diff --git a/src/test/java/org/mariadb/jdbc/unit/util/VersionFactoryTest.java b/src/test/java/org/mariadb/jdbc/unit/util/VersionFactoryTest.java index 38e635272..47905587c 100644 --- a/src/test/java/org/mariadb/jdbc/unit/util/VersionFactoryTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/util/VersionFactoryTest.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.unit.util; import static org.junit.jupiter.api.Assertions.assertNotNull; From 875d9f063c3520e45021a185a8c8c0f2ccedb33c Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 14:14:51 +0200 Subject: [PATCH 08/26] [CONJ-1112] java 19 deprecated methods pre-removal --- .../mariadb/jdbc/export/ExceptionFactory.java | 8 ++++--- .../org/mariadb/jdbc/util/ThreadUtils.java | 19 +++++++++++++++++ .../org/mariadb/jdbc/util/ThreadUtils.java | 21 +++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/mariadb/jdbc/util/ThreadUtils.java create mode 100644 src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java diff --git a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java index 10a9f805d..c0bd6cd1e 100644 --- a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java +++ b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java @@ -14,6 +14,7 @@ import org.mariadb.jdbc.MariaDbPoolConnection; import org.mariadb.jdbc.client.Completion; import org.mariadb.jdbc.message.server.OkPacket; +import org.mariadb.jdbc.util.ThreadUtils; /** * Exception factory. This permit common error logging, with thread id, dump query, and specific @@ -102,7 +103,7 @@ private static String buildMsgText( msg.append("\n name:\"") .append(thread.getName()) .append("\" pid:") - .append(thread.getId()) + .append(ThreadUtils.getId(thread)) .append(" status:") .append(thread.getState()); for (StackTraceElement trace : traces) { @@ -201,7 +202,7 @@ public BatchUpdateException createBatchUpdate( } int MsgResponseNo = responseMsg[i]; if (MsgResponseNo < 1) { - updateCounts[responseIncrement++] = Statement.EXECUTE_FAILED; + updateCounts[0] = Statement.EXECUTE_FAILED; return new BatchUpdateException(updateCounts, sqle); } else if (MsgResponseNo == 1 && res.size() > i && res.get(i) instanceof OkPacket) { updateCounts[i] = (int) ((OkPacket) res.get(i)).getAffectedRows(); @@ -260,7 +261,8 @@ private SQLException createException( // 3948 : mysql load data infile disable if ((errorCode == 4166 || errorCode == 3948 || errorCode == 1148) && !conf.allowLocalInfile()) { return new SQLException( - "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile commands", + "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile" + + " commands", sqlState, errorCode, cause); diff --git a/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java b/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java new file mode 100644 index 000000000..f3301d163 --- /dev/null +++ b/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab +package org.mariadb.jdbc.util; + +import java.util.concurrent.Callable; +import javax.security.auth.Subject; + +public class ThreadUtils { + public static long getId(Thread thread) { + return thread.getId(); + } + + public static void callAs( + final Subject subject, final Callable> action) + throws Exception { + Subject.doAs(subject, action.call()); + } +} diff --git a/src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java b/src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java new file mode 100644 index 000000000..4651e4ceb --- /dev/null +++ b/src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2023 MariaDB Corporation Ab + +package org.mariadb.jdbc.util; +import java.security.PrivilegedExceptionAction; +import java.util.concurrent.Callable; +import javax.security.auth.Subject; + +public class ThreadUtils { + public static long getId(Thread thread) { + return thread.threadId(); + } + + public static void callAs(final Subject subject, + final Callable> action) + throws Exception { + Subject.callAs(subject, action); + } + +} From 6a77c87ab09a5a84e6ec6263419d302d581a1529 Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 14:45:23 +0200 Subject: [PATCH 09/26] [misc] ed25519 update to 0.3.0 --- .../standard/Ed25519PasswordPlugin.java | 2 +- .../standard/ed25519/math/Curve.java | 4 +- .../standard/ed25519/math/Field.java | 14 ++ .../standard/ed25519/math/GroupElement.java | 207 ++++++++++++++---- .../standard/ed25519/math/ScalarOps.java | 3 + .../math/ed25519/Ed25519FieldElement.java | 21 +- .../ed25519/Ed25519LittleEndianEncoding.java | 7 +- .../math/ed25519/Ed25519ScalarOps.java | 141 +++++++----- .../ed25519/spec/EdDSAParameterSpec.java | 5 + 9 files changed, 294 insertions(+), 110 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java index 9b25ed993..c963af900 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java @@ -46,7 +46,7 @@ private static byte[] ed25519SignWithPassword(final String password, final byte[ final byte[] sm = new byte[64 + mlen]; byte[] az = hash.digest(bytePwd); - az[0] &= 248; + az[0] &= (byte) 248; az[31] &= 63; az[31] |= 64; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java index 049f123e4..2e64a85a1 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java @@ -19,6 +19,7 @@ public class Curve implements Serializable { private final GroupElement zeroP3PrecomputedDouble; private final GroupElement zeroPrecomp; + @SuppressWarnings({"this-escape"}) public Curve(Field f, byte[] d, FieldElement I) { this.f = f; this.d = f.fromByteArray(d); @@ -76,8 +77,7 @@ public int hashCode() { @Override public boolean equals(Object o) { if (o == this) return true; - if (!(o instanceof Curve)) return false; - Curve c = (Curve) o; + if (!(o instanceof Curve c)) return false; return f.equals(c.getField()) && d.equals(c.getD()) && I.equals(c.getI()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java index b989b39c8..a556eb5b3 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java @@ -7,6 +7,7 @@ * * @author str4d */ +@SuppressWarnings("all") public class Field implements Serializable { private static final long serialVersionUID = 8746587465875676L; @@ -28,6 +29,7 @@ public class Field implements Serializable { private final Encoding enc; + @SuppressWarnings({"this-escape"}) public Field(int b, byte[] q, Encoding enc) { this.b = b; this.enc = enc; @@ -56,6 +58,18 @@ public int getb() { return b; } + public FieldElement getQ() { + return q; + } + + public FieldElement getQm2() { + return qm2; + } + + public FieldElement getQm5d8() { + return qm5d8; + } + public Encoding getEncoding() { return enc; } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java index bf64655a0..675344e73 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java @@ -24,28 +24,38 @@ * * @author str4d */ +@SuppressWarnings("all") public class GroupElement implements Serializable { private static final long serialVersionUID = 2395879087349587L; + /** Variable is package private only so that tests run. */ final Curve curve; + /** Variable is package private only so that tests run. */ - final Representation repr; + final GroupElement.Representation repr; + /** Variable is package private only so that tests run. */ final FieldElement X; + /** Variable is package private only so that tests run. */ final FieldElement Y; + /** Variable is package private only so that tests run. */ final FieldElement Z; + /** Variable is package private only so that tests run. */ final FieldElement T; + /** * Precomputed table for {@link #scalarMultiply(byte[])}, filled if necessary. * *

Variable is package private only so that tests run. */ final GroupElement[][] precmp; + /** - * Precomputed table for , filled if necessary. + * Precomputed table for {@link #doubleScalarMultiplyVariableTime(GroupElement, byte[], byte[])}, + * filled if necessary. * *

Variable is package private only so that tests run. */ @@ -61,9 +71,10 @@ public class GroupElement implements Serializable { * @param Z The $Z$ coordinate. * @param T The $T$ coordinate. */ + @SuppressWarnings({"this-escape"}) public GroupElement( final Curve curve, - final Representation repr, + final GroupElement.Representation repr, final FieldElement X, final FieldElement Y, final FieldElement Z, @@ -82,9 +93,10 @@ public GroupElement( * @param T The $T$ coordinate. * @param precomputeDouble If true, populate dblPrecmp, else set to null. */ + @SuppressWarnings({"this-escape"}) public GroupElement( final Curve curve, - final Representation repr, + final GroupElement.Representation repr, final FieldElement X, final FieldElement Y, final FieldElement Z, @@ -142,6 +154,7 @@ public GroupElement(final Curve curve, final byte[] s) { * @param precomputeSingleAndDouble If true, populate both precmp and dblPrecmp, else set both to * null. */ + @SuppressWarnings({"this-escape"}) public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleAndDouble) { FieldElement x, y, yy, u, v, v3, vxx, check; y = curve.getField().fromByteArray(s); @@ -179,7 +192,7 @@ public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleA } this.curve = curve; - this.repr = Representation.P3; + this.repr = GroupElement.Representation.P3; this.X = x; this.Y = y; this.Z = curve.getField().ONE; @@ -204,7 +217,7 @@ public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleA */ public static GroupElement p2( final Curve curve, final FieldElement X, final FieldElement Y, final FieldElement Z) { - return new GroupElement(curve, Representation.P2, X, Y, Z, null); + return new GroupElement(curve, GroupElement.Representation.P2, X, Y, Z, null); } /** @@ -244,7 +257,8 @@ public static GroupElement p3( final FieldElement Z, final FieldElement T, final boolean precomputeDoubleOnly) { - return new GroupElement(curve, Representation.P3, X, Y, Z, T, precomputeDoubleOnly); + return new GroupElement( + curve, GroupElement.Representation.P3, X, Y, Z, T, precomputeDoubleOnly); } /** @@ -263,7 +277,7 @@ public static GroupElement p1p1( final FieldElement Y, final FieldElement Z, final FieldElement T) { - return new GroupElement(curve, Representation.P1P1, X, Y, Z, T); + return new GroupElement(curve, GroupElement.Representation.P1P1, X, Y, Z, T); } /** @@ -277,7 +291,7 @@ public static GroupElement p1p1( */ public static GroupElement precomp( final Curve curve, final FieldElement ypx, final FieldElement ymx, final FieldElement xy2d) { - return new GroupElement(curve, Representation.PRECOMP, ypx, ymx, xy2d, null); + return new GroupElement(curve, GroupElement.Representation.PRECOMP, ypx, ymx, xy2d, null); } /** @@ -296,7 +310,7 @@ public static GroupElement cached( final FieldElement YmX, final FieldElement Z, final FieldElement T2d) { - return new GroupElement(curve, Representation.CACHED, YpX, YmX, Z, T2d); + return new GroupElement(curve, GroupElement.Representation.CACHED, YpX, YmX, Z, T2d); } /** @@ -376,15 +390,64 @@ static byte[] slide(final byte[] a) { return r; } + /** + * Gets the curve of the group element. + * + * @return The curve. + */ + public Curve getCurve() { + return this.curve; + } + /** * Gets the representation of the group element. * * @return The representation. */ - public Representation getRepresentation() { + public GroupElement.Representation getRepresentation() { return this.repr; } + /** + * Gets the $X$ value of the group element. This is for most representation the projective $X$ + * coordinate. + * + * @return The $X$ value. + */ + public FieldElement getX() { + return this.X; + } + + /** + * Gets the $Y$ value of the group element. This is for most representation the projective $Y$ + * coordinate. + * + * @return The $Y$ value. + */ + public FieldElement getY() { + return this.Y; + } + + /** + * Gets the $Z$ value of the group element. This is for most representation the projective $Z$ + * coordinate. + * + * @return The $Z$ value. + */ + public FieldElement getZ() { + return this.Z; + } + + /** + * Gets the $T$ value of the group element. This is for most representation the projective $T$ + * coordinate. + * + * @return The $T$ value. + */ + public FieldElement getT() { + return this.T; + } + /** * Converts the group element to an encoded point on the curve. * @@ -411,7 +474,7 @@ public byte[] toByteArray() { * @return The group element in the P2 representation. */ public GroupElement toP2() { - return toRep(Representation.P2); + return toRep(GroupElement.Representation.P2); } /** @@ -420,7 +483,7 @@ public GroupElement toP2() { * @return The group element in the P3 representation. */ public GroupElement toP3() { - return toRep(Representation.P3); + return toRep(GroupElement.Representation.P3); } /** @@ -429,7 +492,7 @@ public GroupElement toP3() { * @return The group element in the P3 representation. */ public GroupElement toP3PrecomputeDouble() { - return toRep(Representation.P3PrecomputedDouble); + return toRep(GroupElement.Representation.P3PrecomputedDouble); } /** @@ -438,7 +501,7 @@ public GroupElement toP3PrecomputeDouble() { * @return The group element in the CACHED representation. */ public GroupElement toCached() { - return toRep(Representation.CACHED); + return toRep(GroupElement.Representation.CACHED); } /** @@ -458,13 +521,15 @@ public GroupElement toCached() { * @param repr The representation to convert to. * @return A new group element in the given representation. */ - private GroupElement toRep(final Representation repr) { + private GroupElement toRep(final GroupElement.Representation repr) { switch (this.repr) { case P2: - if (repr == Representation.P2) { - return p2(this.curve, this.X, this.Y, this.Z); + switch (repr) { + case P2: + return p2(this.curve, this.X, this.Y, this.Z); + default: + throw new IllegalArgumentException(); } - throw new IllegalArgumentException(); case P3: switch (repr) { case P2: @@ -508,15 +573,19 @@ private GroupElement toRep(final Representation repr) { throw new IllegalArgumentException(); } case PRECOMP: - if (repr == Representation.PRECOMP) { - return precomp(this.curve, this.X, this.Y, this.Z); + switch (repr) { + case PRECOMP: + return precomp(this.curve, this.X, this.Y, this.Z); + default: + throw new IllegalArgumentException(); } - throw new IllegalArgumentException(); case CACHED: - if (repr == Representation.CACHED) { - return cached(this.curve, this.X, this.Y, this.Z, this.T); + switch (repr) { + case CACHED: + return cached(this.curve, this.X, this.Y, this.Z, this.T); + default: + throw new IllegalArgumentException(); } - throw new IllegalArgumentException(); default: throw new UnsupportedOperationException(); } @@ -547,7 +616,9 @@ private GroupElement[][] precomputeSingle() { return precmp; } - /** Precomputes table for . */ + /** + * Precomputes table for {@link #doubleScalarMultiplyVariableTime(GroupElement, byte[], byte[])}. + */ private GroupElement[] precomputeDouble() { // Precomputation for double scalar multiplication. // P,3P,5P,7P,9P,11P,13P,15P @@ -677,8 +748,8 @@ public GroupElement dbl() { * @return the P1P1 representation of the result. */ private GroupElement madd(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.PRECOMP) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.PRECOMP) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, D; YpX = this.Y.add(this.X); @@ -705,8 +776,8 @@ private GroupElement madd(GroupElement q) { * @return the P1P1 representation of the result. */ private GroupElement msub(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.PRECOMP) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.PRECOMP) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, D; YpX = this.Y.add(this.X); @@ -750,8 +821,8 @@ private GroupElement msub(GroupElement q) { * @return the P1P1 representation of the result. */ public GroupElement add(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.CACHED) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.CACHED) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, ZZ, D; YpX = this.Y.add(this.X); @@ -777,8 +848,8 @@ public GroupElement add(GroupElement q) { * @return the P1P1 representation of the result. */ public GroupElement sub(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.CACHED) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.CACHED) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, ZZ, D; YpX = Y.add(X); @@ -799,8 +870,11 @@ public GroupElement sub(GroupElement q) { * @return The negative of this group element. */ public GroupElement negate() { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - return this.curve.getZero(Representation.P3).sub(toCached()).toP3PrecomputeDouble(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + return this.curve + .getZero(GroupElement.Representation.P3) + .sub(toCached()) + .toP3PrecomputeDouble(); } @Override @@ -811,8 +885,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof GroupElement)) return false; - GroupElement ge = (GroupElement) obj; + if (!(obj instanceof GroupElement ge)) return false; if (!this.repr.equals(ge.repr)) { try { ge = ge.toRep(this.repr); @@ -891,7 +964,7 @@ GroupElement select(final int pos, final int b) { // 16^i |r_i| B final GroupElement t = this.curve - .getZero(Representation.PRECOMP) + .getZero(GroupElement.Representation.PRECOMP) .cmov(this.precmp[pos][0], Utils.equal(babs, 1)) .cmov(this.precmp[pos][1], Utils.equal(babs, 2)) .cmov(this.precmp[pos][2], Utils.equal(babs, 3)) @@ -922,7 +995,7 @@ public GroupElement scalarMultiply(final byte[] a) { final byte[] e = toRadix16(a); - GroupElement h = this.curve.getZero(Representation.P3); + GroupElement h = this.curve.getZero(GroupElement.Representation.P3); for (i = 1; i < 64; i += 2) { t = select(i / 2, e[i]); h = h.madd(t).toP3(); @@ -938,6 +1011,60 @@ public GroupElement scalarMultiply(final byte[] a) { return h; } + /** + * $r = a * A + b * B$ where $a = a[0]+256*a[1]+\dots+256^{31} a[31]$, $b = + * b[0]+256*b[1]+\dots+256^{31} b[31]$ and $B$ is this point. + * + *

$A$ must have been previously precomputed. + * + * @param A in P3 representation. + * @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$ + * @param b $= b[0]+256*b[1]+\dots+256^{31} b[31]$ + * @return the GroupElement + */ + public GroupElement doubleScalarMultiplyVariableTime( + final GroupElement A, final byte[] a, final byte[] b) { + // TODO-CR BR: A check that this is the base point is needed. + final byte[] aslide = slide(a); + final byte[] bslide = slide(b); + + GroupElement r = this.curve.getZero(GroupElement.Representation.P2); + + int i; + for (i = 255; i >= 0; --i) { + if (aslide[i] != 0 || bslide[i] != 0) break; + } + + for (; i >= 0; --i) { + GroupElement t = r.dbl(); + + if (aslide[i] > 0) { + t = t.toP3().madd(A.dblPrecmp[aslide[i] / 2]); + } else if (aslide[i] < 0) { + t = t.toP3().msub(A.dblPrecmp[(-aslide[i]) / 2]); + } + + if (bslide[i] > 0) { + t = t.toP3().madd(this.dblPrecmp[bslide[i] / 2]); + } else if (bslide[i] < 0) { + t = t.toP3().msub(this.dblPrecmp[(-bslide[i]) / 2]); + } + + r = t.toP2(); + } + + return r; + } + + /** + * Verify that a point is on its curve. + * + * @return true if the point lies on its curve. + */ + public boolean isOnCurve() { + return isOnCurve(curve); + } + /** * Verify that a point is on the curve. * diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java index c52b7f26f..2779e4e07 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.plugin.authentication.standard.ed25519.math; public interface ScalarOps { diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java index ff72cb62f..c42c5b53a 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java @@ -2,8 +2,7 @@ import java.util.Arrays; import org.mariadb.jdbc.plugin.authentication.standard.ed25519.Utils; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.Field; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.FieldElement; +import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.*; /** * Class to represent a field element of the finite field $p = 2^{255} - 19$ elements. @@ -286,6 +285,16 @@ public FieldElement multiply(FieldElement val) { long f9g8_19 = t[9] * (long) g8_19; long f9g9_38 = f9_2 * (long) g9_19; + /** + * Remember: 2^255 congruent 19 modulo p. h = h0 * 2^0 + h1 * 2^26 + h2 * 2^(26+25) + h3 * + * 2^(26+25+26) + ... + h9 * 2^(5*26+5*25). So to get the real number we would have to multiply + * the coefficients with the corresponding powers of 2. To get an idea what is going on below, + * look at the calculation of h0: h0 is the coefficient to the power 2^0 so it collects (sums) + * all products that have the power 2^0. f0 * g0 really is f0 * 2^0 * g0 * 2^0 = (f0 * g0) * + * 2^0. f1 * g9 really is f1 * 2^26 * g9 * 2^230 = f1 * g9 * 2^256 = 2 * f1 * g9 * 2^255 + * congruent 2 * 19 * f1 * g9 * 2^0 modulo p. f2 * g8 really is f2 * 2^51 * g8 * 2^204 = f2 * g8 + * * 2^255 congruent 19 * f2 * g8 * 2^0 modulo p. and so on... + */ long h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; @@ -501,6 +510,11 @@ public FieldElement square() { long f8f9_38 = f8 * (long) f9_38; long f9f9_38 = f9 * (long) f9_38; + /** + * Same procedure as in multiply, but this time we have a higher symmetry leading to less + * summands. e.g. f1f9_76 really stands for f1 * 2^26 * f9 * 2^230 + f9 * 2^230 + f1 * 2^26 + * congruent 2 * 2 * 19 * f1 * f9 2^0 modulo p. + */ long h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; long h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; long h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; @@ -1038,8 +1052,7 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof Ed25519FieldElement)) return false; - Ed25519FieldElement fe = (Ed25519FieldElement) obj; + if (!(obj instanceof Ed25519FieldElement fe)) return false; return 1 == Utils.equal(toByteArray(), fe.toByteArray()); } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java index 774c40a37..61885e112 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java @@ -1,7 +1,6 @@ package org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.Encoding; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.FieldElement; +import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.*; /** * Helper class for encoding/decoding from/to the 32 byte representation. @@ -34,6 +33,8 @@ static long load_4(byte[] in, int offset) { * *

The idea for the modulo $p$ reduction algorithm is as follows: * + *

Assumption:

+ * *
    *
  • $p = 2^{255} - 19$ *
  • $h = h_0 + 2^{25} * h_1 + 2^{(26+25)} * h_2 + \dots + 2^{230} * h_9$ where $0 \le |h_i| @@ -44,7 +45,7 @@ static long load_4(byte[] in, int offset) { * *

    Then $q = [2^{-255} * (h + 19 * 2^{-25} * h_9 + 1/2)]$ where $[x] = floor(x)$. * - *

    Proof: + *

    Proof:

    * *

    We begin with some very raw estimation for the bounds of some expressions: * diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java index 0f9a518f5..ca892394c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java @@ -9,6 +9,9 @@ */ package org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519; +import static org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519.Ed25519LittleEndianEncoding.load_3; +import static org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519.Ed25519LittleEndianEncoding.load_4; + import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ScalarOps; /** @@ -31,30 +34,30 @@ public class Ed25519ScalarOps implements ScalarOps { */ public byte[] reduce(byte[] s) { // s0,..., s22 have 21 bits, s23 has 29 bits - long s0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(s, 0); - long s1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 2) >> 5); - long s2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 5) >> 2); - long s3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 7) >> 7); - long s4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 10) >> 4); - long s5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 13) >> 1); - long s6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 15) >> 6); - long s7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 18) >> 3); - long s8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(s, 21); - long s9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 23) >> 5); - long s10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 26) >> 2); - long s11 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 28) >> 7); - long s12 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 31) >> 4); - long s13 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 34) >> 1); - long s14 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 36) >> 6); - long s15 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 39) >> 3); - long s16 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(s, 42); - long s17 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 44) >> 5); - long s18 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 47) >> 2); - long s19 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 49) >> 7); - long s20 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 52) >> 4); - long s21 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 55) >> 1); - long s22 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 57) >> 6); - long s23 = (Ed25519LittleEndianEncoding.load_4(s, 60) >> 3); + long s0 = 0x1FFFFF & load_3(s, 0); + long s1 = 0x1FFFFF & (load_4(s, 2) >> 5); + long s2 = 0x1FFFFF & (load_3(s, 5) >> 2); + long s3 = 0x1FFFFF & (load_4(s, 7) >> 7); + long s4 = 0x1FFFFF & (load_4(s, 10) >> 4); + long s5 = 0x1FFFFF & (load_3(s, 13) >> 1); + long s6 = 0x1FFFFF & (load_4(s, 15) >> 6); + long s7 = 0x1FFFFF & (load_3(s, 18) >> 3); + long s8 = 0x1FFFFF & load_3(s, 21); + long s9 = 0x1FFFFF & (load_4(s, 23) >> 5); + long s10 = 0x1FFFFF & (load_3(s, 26) >> 2); + long s11 = 0x1FFFFF & (load_4(s, 28) >> 7); + long s12 = 0x1FFFFF & (load_4(s, 31) >> 4); + long s13 = 0x1FFFFF & (load_3(s, 34) >> 1); + long s14 = 0x1FFFFF & (load_4(s, 36) >> 6); + long s15 = 0x1FFFFF & (load_3(s, 39) >> 3); + long s16 = 0x1FFFFF & load_3(s, 42); + long s17 = 0x1FFFFF & (load_4(s, 44) >> 5); + long s18 = 0x1FFFFF & (load_3(s, 47) >> 2); + long s19 = 0x1FFFFF & (load_4(s, 49) >> 7); + long s20 = 0x1FFFFF & (load_4(s, 52) >> 4); + long s21 = 0x1FFFFF & (load_3(s, 55) >> 1); + long s22 = 0x1FFFFF & (load_4(s, 57) >> 6); + long s23 = (load_4(s, 60) >> 3); long carry0; long carry1; long carry2; @@ -73,6 +76,21 @@ public byte[] reduce(byte[] s) { long carry15; long carry16; + /** + * Lots of magic numbers :) To understand what's going on below, note that + * + *

    (1) q = 2^252 + q0 where q0 = 27742317777372353535851937790883648493. (2) s11 is the + * coefficient of 2^(11*21), s23 is the coefficient of 2^(^23*21) and 2^252 = 2^((23-11) * 21)). + * (3) 2^252 congruent -q0 modulo q. (4) -q0 = 666643 * 2^0 + 470296 * 2^21 + 654183 * 2^(2*21) + * - 997805 * 2^(3*21) + 136657 * 2^(4*21) - 683901 * 2^(5*21) + * + *

    Thus s23 * 2^(23*11) = s23 * 2^(12*21) * 2^(11*21) = s3 * 2^252 * 2^(11*21) congruent s23 + * * (666643 * 2^0 + 470296 * 2^21 + 654183 * 2^(2*21) - 997805 * 2^(3*21) + 136657 * 2^(4*21) - + * 683901 * 2^(5*21)) * 2^(11*21) modulo q = s23 * (666643 * 2^(11*21) + 470296 * 2^(12*21) + + * 654183 * 2^(13*21) - 997805 * 2^(14*21) + 136657 * 2^(15*21) - 683901 * 2^(16*21)). + * + *

    The same procedure is then applied for s22,...,s18. + */ s11 += s23 * 666643; s12 += s23 * 470296; s13 += s23 * 654183; @@ -127,6 +145,7 @@ public byte[] reduce(byte[] s) { // not used again // s18 = 0; + /** Time to reduce the coefficient in order not to get an overflow. */ carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; @@ -162,6 +181,7 @@ public byte[] reduce(byte[] s) { s16 += carry15; s15 -= carry15 << 21; + /** Continue with above procedure. */ s5 += s17 * 666643; s6 += s17 * 470296; s7 += s17 * 654183; @@ -216,6 +236,7 @@ public byte[] reduce(byte[] s) { // set below // s12 = 0; + /** Reduce coefficients again. */ carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; @@ -400,42 +421,42 @@ public byte[] reduce(byte[] s) { *

    See the comments in {@link #reduce(byte[])} for an explanation of the algorithm. */ public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c) { - long a0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(a, 0); - long a1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 2) >> 5); - long a2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 5) >> 2); - long a3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 7) >> 7); - long a4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 10) >> 4); - long a5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 13) >> 1); - long a6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 15) >> 6); - long a7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 18) >> 3); - long a8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(a, 21); - long a9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 23) >> 5); - long a10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 26) >> 2); - long a11 = (Ed25519LittleEndianEncoding.load_4(a, 28) >> 7); - long b0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(b, 0); - long b1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 2) >> 5); - long b2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 5) >> 2); - long b3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 7) >> 7); - long b4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 10) >> 4); - long b5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 13) >> 1); - long b6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 15) >> 6); - long b7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 18) >> 3); - long b8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(b, 21); - long b9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 23) >> 5); - long b10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 26) >> 2); - long b11 = (Ed25519LittleEndianEncoding.load_4(b, 28) >> 7); - long c0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(c, 0); - long c1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 2) >> 5); - long c2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 5) >> 2); - long c3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 7) >> 7); - long c4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 10) >> 4); - long c5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 13) >> 1); - long c6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 15) >> 6); - long c7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 18) >> 3); - long c8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(c, 21); - long c9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 23) >> 5); - long c10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 26) >> 2); - long c11 = (Ed25519LittleEndianEncoding.load_4(c, 28) >> 7); + long a0 = 0x1FFFFF & load_3(a, 0); + long a1 = 0x1FFFFF & (load_4(a, 2) >> 5); + long a2 = 0x1FFFFF & (load_3(a, 5) >> 2); + long a3 = 0x1FFFFF & (load_4(a, 7) >> 7); + long a4 = 0x1FFFFF & (load_4(a, 10) >> 4); + long a5 = 0x1FFFFF & (load_3(a, 13) >> 1); + long a6 = 0x1FFFFF & (load_4(a, 15) >> 6); + long a7 = 0x1FFFFF & (load_3(a, 18) >> 3); + long a8 = 0x1FFFFF & load_3(a, 21); + long a9 = 0x1FFFFF & (load_4(a, 23) >> 5); + long a10 = 0x1FFFFF & (load_3(a, 26) >> 2); + long a11 = (load_4(a, 28) >> 7); + long b0 = 0x1FFFFF & load_3(b, 0); + long b1 = 0x1FFFFF & (load_4(b, 2) >> 5); + long b2 = 0x1FFFFF & (load_3(b, 5) >> 2); + long b3 = 0x1FFFFF & (load_4(b, 7) >> 7); + long b4 = 0x1FFFFF & (load_4(b, 10) >> 4); + long b5 = 0x1FFFFF & (load_3(b, 13) >> 1); + long b6 = 0x1FFFFF & (load_4(b, 15) >> 6); + long b7 = 0x1FFFFF & (load_3(b, 18) >> 3); + long b8 = 0x1FFFFF & load_3(b, 21); + long b9 = 0x1FFFFF & (load_4(b, 23) >> 5); + long b10 = 0x1FFFFF & (load_3(b, 26) >> 2); + long b11 = (load_4(b, 28) >> 7); + long c0 = 0x1FFFFF & load_3(c, 0); + long c1 = 0x1FFFFF & (load_4(c, 2) >> 5); + long c2 = 0x1FFFFF & (load_3(c, 5) >> 2); + long c3 = 0x1FFFFF & (load_4(c, 7) >> 7); + long c4 = 0x1FFFFF & (load_4(c, 10) >> 4); + long c5 = 0x1FFFFF & (load_3(c, 13) >> 1); + long c6 = 0x1FFFFF & (load_4(c, 15) >> 6); + long c7 = 0x1FFFFF & (load_3(c, 18) >> 3); + long c8 = 0x1FFFFF & load_3(c, 21); + long c9 = 0x1FFFFF & (load_4(c, 23) >> 5); + long c10 = 0x1FFFFF & (load_3(c, 26) >> 2); + long c11 = (load_4(c, 28) >> 7); long s0; long s1; long s2; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java index 0fa7df90f..e81547f11 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java @@ -22,6 +22,7 @@ * * @author str4d */ +@SuppressWarnings("all") public class EdDSAParameterSpec implements AlgorithmParameterSpec, Serializable { private static final long serialVersionUID = 8274987108472012L; private final Curve curve; @@ -60,6 +61,10 @@ public String getHashAlgorithm() { return hashAlgo; } + public ScalarOps getScalarOps() { + return sc; + } + /** * @return the base (generator) */ From c50b6fa0fdcbe8e1265c1ee683db395e63210340 Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 14:56:30 +0200 Subject: [PATCH 10/26] [misc] correct missing export --- bnd.bnd | 2 +- src/main/java9/module-info.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bnd.bnd b/bnd.bnd index f189fdab7..c984e13de 100644 --- a/bnd.bnd +++ b/bnd.bnd @@ -1,4 +1,4 @@ -Export-Package: org.mariadb.jdbc;org.mariadb.jdbc.client;org.mariadb.jdbc.client.util;org.mariadb.jdbc.client.socket;org.mariadb.jdbc.message;org.mariadb.jdbc.type;org.mariadb.jdbc.export;org.mariadb.jdbc.plugin;org.mariadb.jdbc.plugin.codec;org.mariadb.jdbc.plugin.authentication.standard;org.mariadb.jdbc.plugin.authentication.addon;org.mariadb.jdbc.plugin.credential.aws;org.mariadb.jdbc.plugin.credential.env;org.mariadb.jdbc.plugin.credential.system;org.mariadb.jdbc.plugin.tls.main +Export-Package: org.mariadb.jdbc;org.mariadb.jdbc.client;org.mariadb.jdbc.client.util;org.mariadb.jdbc.util.constants;org.mariadb.jdbc.client.socket;org.mariadb.jdbc.message;org.mariadb.jdbc.type;org.mariadb.jdbc.export;org.mariadb.jdbc.plugin;org.mariadb.jdbc.plugin.codec;org.mariadb.jdbc.plugin.authentication.standard;org.mariadb.jdbc.plugin.authentication.addon;org.mariadb.jdbc.plugin.credential.aws;org.mariadb.jdbc.plugin.credential.env;org.mariadb.jdbc.plugin.credential.system;org.mariadb.jdbc.plugin.tls.main Import-Package: \ javax.naming,\ diff --git a/src/main/java9/module-info.java b/src/main/java9/module-info.java index 5896c2823..5f1814779 100644 --- a/src/main/java9/module-info.java +++ b/src/main/java9/module-info.java @@ -21,6 +21,7 @@ exports org.mariadb.jdbc.message; exports org.mariadb.jdbc.type; exports org.mariadb.jdbc.export; + exports org.mariadb.jdbc.util.constants; exports org.mariadb.jdbc.plugin; exports org.mariadb.jdbc.plugin.codec; exports org.mariadb.jdbc.plugin.authentication.standard; From 04f99d50ccb5d9ae26e70305985c5ea777d8bd20 Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 14:58:09 +0200 Subject: [PATCH 11/26] [misc] spotless addition to ensure code style compatible with java 21 --- CHANGELOG.md | 26 +++--- pom.xml | 92 ++++++++++++++----- .../integration/CredentialPluginTest.java | 5 +- 3 files changed, 84 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28811f9ab..6c0ed4f14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,9 +87,9 @@ [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.0...3.1.1) - 3.0.10 bug fix: - - 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 + - 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 - CONJ-1036 org.mariadb.jdbc.client.socket.impl.PacketWriter.writeAscii() broken in 3.1.0 ## [3.0.10](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.10) (Jan 2023) @@ -144,7 +144,7 @@ ##### Notable Changes * small performance improvement - * [CONJ-1010] improve client side prepared parameter parameter substitution + * [CONJ-1010] improve client side prepared parameter parameter substitution ##### Bugs Fixed @@ -250,7 +250,7 @@ [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.1-beta...3.0.2-rc) * CONJ-879 Java 9 module full support - * Aws IAM credential now use sdk v2 authentication that support java 9 modularity + * Aws IAM credential now use sdk v2 authentication that support java 9 modularity * CONJ-896 Ensure pool connections validation when a socket fail * CONJ-897 Ensure having connection's thread id in Exception / debug logs @@ -288,12 +288,12 @@ This version is a total rewrite of java driver. * complete rewrite, code clarification, reduced size (15%), more than 90% coverage tested. * Encoding/decoding implementation are now registred by Codec, permitting codec registry implementation - * example support of Geometry Object + * example support of Geometry Object * Permit authentication plugin restriction by option `restrictedAuth` * performance improvement: - * Prepare and execution are now using pipelining when using option `useServerPrepStmts` - * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata ( - see https://jira.mariadb.org/browse/MDEV-19237) + * Prepare and execution are now using pipelining when using option `useServerPrepStmts` + * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata ( + see https://jira.mariadb.org/browse/MDEV-19237) correction: @@ -1193,10 +1193,10 @@ Different performance improvement have been done : up to 7% of query time, reduced to 3%. * Better UTF-8 decoding avoiding memory consumption and gain 1-2% query time for big String. * client parsing optimization : rewriteBatchedStatements (insert into ab (i) values (1) and insert into ab (i) values ( - 2) rewritten as insert into ab (i) values (1), (2)) - is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to - contain - query). + 2) rewritten as insert into ab (i) values (1), (2)) + is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to + contain + query). * there was some memory wastage when query return big resultset (> 10kb), slowing query. * ... diff --git a/pom.xml b/pom.xml index 9624bddda..5b0d5d211 100644 --- a/pom.xml +++ b/pom.xml @@ -21,10 +21,11 @@ 5.0.0 UTF-8 1.4.4 - 0.8.8 - 3.2.0 + 0.8.10 + 3.3.0 8.0.31 6.3.1 + 2.40.0 @@ -79,7 +80,7 @@ software.amazon.awssdk bom - 2.18.10 + 2.21.1 pom import @@ -146,6 +147,22 @@ true + + compile-java-19 + compile + + compile + + + 19 + 19 + 19 + + ${project.basedir}/src/main/java19 + + true + + @@ -232,33 +249,58 @@ - com.theoryinpractise - googleformatter-maven-plugin - 1.7.3 - - - reformat-sources - - false + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + + + *.md + .gitignore + + + Ed25519*.java + + + + + + true + 2 + + + + + + src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/**/*.java + + + + src/main/java/**/*.java + src/test/java/**/*.java + + + 1.18.1 - true - true - false - false - false - 100 - - - format - - process-sources - - + true + true + com.google.googlejavaformat:google-java-format + + + ${project.basedir}/licenseheader.txt + + + org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M7 + 3.1.2 diff --git a/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java b/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java index 0c261f459..747dc38ee 100644 --- a/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/CredentialPluginTest.java @@ -22,7 +22,10 @@ public class CredentialPluginTest extends Common { @BeforeAll public static void beforeTest() throws SQLException { String version = System.getProperty("java.version"); - int majorVersion = Integer.parseInt(version.substring(0, version.indexOf("."))); + int majorVersion = + (version.indexOf(".") >= 0) + ? Integer.parseInt(version.substring(0, version.indexOf("."))) + : Integer.parseInt(version); Assumptions.assumeTrue(majorVersion < 17); Assumptions.assumeTrue(isMariaDBServer()); From 7b197fe6fcea3993e8ec701cc36d629a2a6383ff Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 16:45:14 +0200 Subject: [PATCH 12/26] [misc] pattern matching in instanceof correction for java 8 support --- src/main/java/org/mariadb/jdbc/BasePreparedStatement.java | 3 ++- src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java | 3 ++- .../plugin/authentication/standard/ed25519/math/Curve.java | 3 ++- .../authentication/standard/ed25519/math/GroupElement.java | 3 ++- .../standard/ed25519/math/ed25519/Ed25519FieldElement.java | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java index 1f290c7bc..9915f43ee 100644 --- a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java @@ -1192,7 +1192,8 @@ private void setInternalObject( "HY000", e); } - } else if (obj instanceof Number bd) { + } else if (obj instanceof Number) { + Number bd = (Number) obj; switch (targetSqlType) { case Types.TINYINT: setByte(parameterIndex, bd.byteValue()); diff --git a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java index d2c7805a9..d6700f6c0 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java @@ -232,7 +232,8 @@ public Configuration getConf() { @Override public boolean isSameRM(XAResource xaResource) { - if (xaResource instanceof MariaDbXAResource other) { + if (xaResource instanceof MariaDbXAResource) { + MariaDbXAResource other = (MariaDbXAResource) xaResource; return other.getConf().equals(this.getConf()); } return false; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java index 2e64a85a1..b96191560 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java @@ -77,7 +77,8 @@ public int hashCode() { @Override public boolean equals(Object o) { if (o == this) return true; - if (!(o instanceof Curve c)) return false; + if (!(o instanceof Curve)) return false; + Curve c = (Curve) o; return f.equals(c.getField()) && d.equals(c.getD()) && I.equals(c.getI()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java index 675344e73..1df002360 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java @@ -885,7 +885,8 @@ public int hashCode() { @Override public boolean equals(Object obj) { if (obj == this) return true; - if (!(obj instanceof GroupElement ge)) return false; + if (!(obj instanceof GroupElement)) return false; + GroupElement ge = (GroupElement) obj; if (!this.repr.equals(ge.repr)) { try { ge = ge.toRep(this.repr); diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java index c42c5b53a..c2a413a58 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java @@ -1052,7 +1052,8 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (!(obj instanceof Ed25519FieldElement fe)) return false; + if (!(obj instanceof Ed25519FieldElement)) return false; + Ed25519FieldElement fe = (Ed25519FieldElement) obj; return 1 == Utils.equal(toByteArray(), fe.toByteArray()); } From f2c90f9bf7b3ca921966af4d2cfc6c1e89f302fa Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 17:44:22 +0200 Subject: [PATCH 13/26] [misc] test suite using openjdk17 by default --- .travis.yml | 6 +++--- pom.xml | 16 -------------- .../org/mariadb/jdbc/util/ThreadUtils.java | 3 +++ .../org/mariadb/jdbc/util/ThreadUtils.java | 21 ------------------- 4 files changed, 6 insertions(+), 40 deletions(-) delete mode 100644 src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java diff --git a/.travis.yml b/.travis.yml index e338e00bec..8f1c188c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ language: java services: - docker - mysql -jdk: openjdk11 +jdk: openjdk17 addons: hosts: - mariadb.example.com @@ -102,8 +102,8 @@ jobs: - env: srv=mariadb v=11.1 local=1 name: "CS 11.1" - env: srv=mariadb v=10.6 packet=40 - jdk: openjdk17 - name: "CS 10.6 - openjdk 17" + jdk: openjdk11 + name: "CS 10.6 - openjdk 11" - env: srv=mariadb v=10.6 packet=8 name: "CS 10.6 - packet 8M" - env: srv=mariadb v=10.6 local=1 BENCH=1 diff --git a/pom.xml b/pom.xml index 5b0d5d211..cdf810d97 100644 --- a/pom.xml +++ b/pom.xml @@ -147,22 +147,6 @@ true - - compile-java-19 - compile - - compile - - - 19 - 19 - 19 - - ${project.basedir}/src/main/java19 - - true - - diff --git a/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java b/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java index f3301d163..9d72293c3 100644 --- a/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java +++ b/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java @@ -8,6 +8,7 @@ public class ThreadUtils { public static long getId(Thread thread) { + // must be return thread.threadId() for java 19+, but since we support java 8, cannot be removed for now return thread.getId(); } @@ -15,5 +16,7 @@ public static void callAs( final Subject subject, final Callable> action) throws Exception { Subject.doAs(subject, action.call()); + // must be for java 18+, but since we support java 8, cannot be removed for now + // Subject.callAs(subject, action); } } diff --git a/src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java b/src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java deleted file mode 100644 index 4651e4ceb..000000000 --- a/src/main/java19/org/mariadb/jdbc/util/ThreadUtils.java +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1-or-later -// Copyright (c) 2012-2014 Monty Program Ab -// Copyright (c) 2023 MariaDB Corporation Ab - -package org.mariadb.jdbc.util; -import java.security.PrivilegedExceptionAction; -import java.util.concurrent.Callable; -import javax.security.auth.Subject; - -public class ThreadUtils { - public static long getId(Thread thread) { - return thread.threadId(); - } - - public static void callAs(final Subject subject, - final Callable> action) - throws Exception { - Subject.callAs(subject, action); - } - -} From 029213696935630a7c9c5763a4d4f07f8f5c7def Mon Sep 17 00:00:00 2001 From: rusher Date: Wed, 18 Oct 2023 17:58:42 +0200 Subject: [PATCH 14/26] [misc] correct UnixDomainSocket not used sun_family variable, but mandatory for JNI --- CHANGELOG.md | 114 +++++++++--------- CONTRIBUTING.md | 6 +- pom.xml | 8 +- .../org/mariadb/jdbc/DatabaseMetaData.java | 44 +++---- .../client/socket/impl/UnixDomainSocket.java | 3 + .../org/mariadb/jdbc/util/ThreadUtils.java | 3 +- 6 files changed, 88 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c0ed4f14..aee5f2ed9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,10 @@ ##### Notable Changes * CONJ-920 Java batched statements with optimistic locking failing. the option `useBulkStmts` is now disable by default, - a new option `useBulkStmtsForInserts` is enabled by default, permitting using bulk for INSERT commands only. This - permits optimistic behavior working by default. + a new option `useBulkStmtsForInserts` is enabled by default, permitting using bulk for INSERT commands only. This + permits optimistic behavior working by default. * CONJ-1084 When using maxscale 23.08.0+, and a maxscale node fails, connector will now priorize reconnection to the - maxscale node having less connection, to ensure repartition after failover + maxscale node having less connection, to ensure repartition after failover * CONJ-1088 Implement `databaseTerm` option for mysql compatibility * CONJ-1096 adding option `useLocalSessionState` to permit avoiding queries when application only use JDBC methods. @@ -18,7 +18,7 @@ * CONJ-1075 LOAD DATA INFILE is broken on windows * CONJ-1079 getGeneratedKeys after batch will not return all generated id's if first batch command return no generated - id. + id. * CONJ-1080 mariadb Java connector sslMode=verify-ca complaining unable to find trust certificate. * CONJ-1082 Multiple session system variables parsing fails * CONJ-1083 Using /*client prepare*/ prefix to force client side prepared statement @@ -37,7 +37,7 @@ [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.9...2.7.10) * CONJ-1091 Ensure setting connectTimeout as timeout for socket timeout until connection is done. This permit to set a - connectTimeout, while socketTimeout can still be set to 0 + connectTimeout, while socketTimeout can still be set to 0 ## [3.1.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.4) (Apr 2023) @@ -47,7 +47,7 @@ * CONJ-1070 getBlob on TEXT columns throw Exception * CONJ-1071 Error response during Bulk execution might result in connection wrong state * CONJ-1067 When some numeric data types are set to UNSIGNED, ResultSetMetaData.getColumnTypeName() does not return - UNSIGNED + UNSIGNED ## [3.1.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.3) (Mar 2023) @@ -87,9 +87,9 @@ [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.0...3.1.1) - 3.0.10 bug fix: - - 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 + - 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 - CONJ-1036 org.mariadb.jdbc.client.socket.impl.PacketWriter.writeAscii() broken in 3.1.0 ## [3.0.10](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.10) (Jan 2023) @@ -144,7 +144,7 @@ ##### Notable Changes * small performance improvement - * [CONJ-1010] improve client side prepared parameter parameter substitution + * [CONJ-1010] improve client side prepared parameter parameter substitution ##### Bugs Fixed @@ -207,7 +207,7 @@ * [CONJ-922] DECIMAL overflow for long/int/short not throwing exception * [CONJ-924] NULL column type might result in java.lang.IllegalArgumentException: Unexpected datatype NULL * [CONJ-926] Client restrict authentication to 'mysql_native_password,client_ed25519,auth_gssapi_client' if - restrictedAuth parameter is not set + restrictedAuth parameter is not set * [CONJ-924] NULL column test correction * [CONJ-923] correctly return 64 bits generated id / updated rows * [CONJ-933] load-balancing failover doesn't timeout @@ -225,14 +225,14 @@ [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.2-rc...3.0.3) * [CONJ-908] correct Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) to return - generated keys + generated keys * [CONJ-909] adding createDatabaseIfNotExist option for 2.x compatibility * [CONJ-910] permit jdbc:mysql scheme when connection string contains "permitMysqlScheme" for compatibility * [CONJ-913] Avoid executing additional command on connection for faster connection creation * [CONJ-912] remove security manager code (JEP 411) * [CONJ-911] enable keep-alive by default * failover improvement. some specific commands not in transaction are considered to be replayed in case of failover, - like PING, PREPARE, ROLLBACK, ... + like PING, PREPARE, ROLLBACK, ... * CONJ-705 parameter metadata get parameter count even when query cannot be prepared * prepareStatement.addBatch must initialize with previous set * Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) must return generated keys @@ -250,7 +250,7 @@ [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.1-beta...3.0.2-rc) * CONJ-879 Java 9 module full support - * Aws IAM credential now use sdk v2 authentication that support java 9 modularity + * Aws IAM credential now use sdk v2 authentication that support java 9 modularity * CONJ-896 Ensure pool connections validation when a socket fail * CONJ-897 Ensure having connection's thread id in Exception / debug logs @@ -288,17 +288,17 @@ This version is a total rewrite of java driver. * complete rewrite, code clarification, reduced size (15%), more than 90% coverage tested. * Encoding/decoding implementation are now registred by Codec, permitting codec registry implementation - * example support of Geometry Object + * example support of Geometry Object * Permit authentication plugin restriction by option `restrictedAuth` * performance improvement: - * Prepare and execution are now using pipelining when using option `useServerPrepStmts` - * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata ( - see https://jira.mariadb.org/browse/MDEV-19237) + * Prepare and execution are now using pipelining when using option `useServerPrepStmts` + * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata ( + see https://jira.mariadb.org/browse/MDEV-19237) correction: * CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock - exception + exception * CONJ-858 Properties parameter that differ from string not taken in account ### Easy logging @@ -348,7 +348,7 @@ Since available only with java 11, setting this option with java < 11 will have * CONJ-855 throwing more specific exception for updatable result-set that can not be updated by ResultSet * CONJ-857 Remove use of mysql.proc table, relying on information_schema.parameters * CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock - exception + exception * CONJ-866 long binary parsing improvement * CONJ-871 OSGi: Missing Import-Package in Connector/J bundle (javax.sql.rowset.serial) * CONJ-878 option serverSslCert file location @@ -363,7 +363,7 @@ Since available only with java 11, setting this option with java < 11 will have * CONJ-847 NPE at UpdatableResultSet#close * CONJ-849 driver now doesn't close connection caused java.io.NotSerializableException as a result of incorrect data - bind to a prepared statement parameter + bind to a prepared statement parameter * CONJ-850 MariaDbResultSetMetaData#getPrecision(int) now returns correct length for character data * CONJ-851 metadata getBestRowIdentifier incompatibility with MySQL 8 correction * CONJ-853 Support Aurora cluster custom endpoints @@ -380,7 +380,7 @@ Since available only with java 11, setting this option with java < 11 will have * CONJ-842 Byte array parameters are now send as long data * CONJ-837 prepared statement cache leak on ResultSet CONCUR_UPDATABLE concurrency * CONJ-843 ParameterMetaData::getParameterType for CallableStatement parameter return expected "BINARY" value for BINARY - type + type minor: @@ -424,7 +424,7 @@ minor: * CONJ-776 - Temporal Data Tables are not listed in metadata * CONJ-785 - corrected escape sequence for multiple backslash escape * CONJ-786 - Connection.setReadOnly(true ) with option `assureReadOnly` now force read only connection even for mono - server* + server* * CONJ-795 - permit resultset.getRow() for TYPE_FORWARD_ONLY when streaming * CONJ-797 - Connector set UTF8mb4 equivalent in case of server configured with UTF8mb3 collation * CONJ-800 - implement Statement setEscapeProcessing to avoid escape @@ -441,7 +441,7 @@ minor: [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.4...2.6.0) * CONJ-768 - Check Galera allowed state when connecting when option `galeraAllowedState` is set, and not only on - validation + validation * CONJ-759 - on failover, catalog changed might not be set when automatically recreating a connection. * CONJ-761 - remove unnecessary dependencies for fedora tar creation * CONJ-763 - Custom SocketFactory now can change options @@ -489,11 +489,11 @@ minor: [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.4...2.5.0) * CONJ-663 - Client authentication plugins are now defined as services. The driver has 2 new - plugins `caching_sha2_password` and `sha256_password plugin` for MySQL compatibility + plugins `caching_sha2_password` and `sha256_password plugin` for MySQL compatibility * CONJ-733 - Credential service: AWS IAM authentication * CONJ-727 - Support configuration of custom SSLSocketFactory * CONJ-561 - JDBC 4.3 partial implementation java.sql.Statement methods isSimpleIdentifier, enquoteIdentifier, - enquoteLiteral and enquoteNCharLiteral + enquoteLiteral and enquoteNCharLiteral * CONJ-692 - ConnectionPoolDataSource interface addition to MariaDbPoolDataSource * CONJ-563 - closing possible option batch thread on driver registration. * CONJ-732 - Driver getPropertyInfo returns no options' information when url is empty @@ -506,7 +506,7 @@ minor: * CONJ-724 - Do not ignore the Calendar parameter in ResultSet#getTime(int, Calendar) * CONJ-725 - Connection Failure when using PAM authenticated user on 10.4 MariaDB server * CONJ-729 - master-slave regression: commit on read-only server Executed only when there is an active transaction on - master connection + master connection * CONJ-726 - removing possible NPE after failover on aurora cluster ## [2.4.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.3) (02 Jul. 2019) @@ -532,9 +532,9 @@ Bugs * CONJ-711 - Xid format id is unsigned integer, currently sending as signed value. * CONJ-700 - autoReconnect=true on Basic Failover doesn't reconnect * CONJ-707 - failover might throw an unexpected exception with using "failover"/"sequential" configuration on socket - error + error * CONJ-709 - includeThreadDumpInDeadlockExceptions is thrown only if option includeInnodbStatusInDeadlockExceptions is - set + set * CONJ-710 - Throw complete stackTrace when having an exception on XA Commands * CONJ-714 - Error on connection on galera server when in detached mode. * CONJ-701 - typo in error message in SelectResultSet.java @@ -555,7 +555,7 @@ Bugs * CONJ-687 - addition of option "useMysqlMetadata" to permit MySQL meta compatibility * misc - java PID using java 9 ProcessHandle if existing, relying on JNA if present * CONJ-682 - internal pool correction: when receiving an RST during connection validation, the pool will end up throwing - connection timeout exception in place of reusing another connection. + connection timeout exception in place of reusing another connection. ## [2.4.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.0) (28 Jan. 2019) @@ -633,16 +633,16 @@ This option still makes sense, since for big batch is way faster, but will not b * CONJ-628 - optimization to read metadata faster * CONJ-637 - java.sql.Driver class implement DriverPropertyInfo[] getPropertyInfo, permitting listing options on - querying tools + querying tools * CONJ-639 - enabledSslProtocolSuites does not include TLSv1.2 by default * CONJ-641 - update maven test dependencies for java 10 compatibility * CONJ-643 - PreparedStatement::getParameterMetaData always returns VARSTRING as type resulting in downstream libraries - interpreting values wrongly + interpreting values wrongly ##= Bug correction: * CONJ-616 - correction on possible NPE on getConnection when using failover configuration and master is down, not - throwing a proper exception + throwing a proper exception * CONJ-636 - Error in batch might throw a NPE and not the proper Exception ## [2.2.6](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.6) (19 Jul. 2018) @@ -682,7 +682,7 @@ Bug correction: * CONJ-595 - Create option to configure DONOR/DESYNCED Galera nodes to be unavailable for load-balancing * CONJ-605 - Newlines where breaking calling stored procedures * CONJ-609 - Using getDate with function DATE_ADD() with parameter using string format where return wrong result using - binary protocol + binary protocol * CONJ-610 - Option "allowMasterDownConnection" improvement on connection validation and Exceptions on master down ## [2.2.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.4) (04 May. 2018) @@ -732,10 +732,10 @@ Bug correction: Bug correction: * CONJ-529 - failover : the driver will pause for 250ms if no servers are available before attempting to reconnect - another time + another time * CONJ-548 - don't use COM_STMT_BULK_EXECUTE for INSERT ... SELECT statements * CONJ-549 - correction on connection reset when using MariaDbPoolDataSource with options useServerPrepStmts and - useResetConnection enabled + useResetConnection enabled * CONJ-555 - failover caused by client timeout must not reuse connection * CONJ-558 - removing extra ".0" to resultset.getString() value for FLOAT/DOUBLE fields * CONJ-550 - fetching state correction when reusing statement without having read all results @@ -753,7 +753,7 @@ MariaDB has now 2 different Datasource implementation : * MariaDbDataSource : Basic implementation. A new connection each time method getConnection() is called. * MariaDbPoolDataSource : Connection pooling implementation. MariaDB Driver will keep a pool of connection and borrow - Connections when asked for it. + Connections when asked for it. New options @@ -779,7 +779,7 @@ Bug : * CONJ-532 - correction Statement.getMoreResults() for multi-queries * CONJ-533 - PrepareStatement.setTime() may insert incorrect time according to current timezone, time and option " - useLegacyDatetimeCode" + useLegacyDatetimeCode" * CONJ-535 - correction on numerical getter for big BIT data type fields * CONJ-541 - Fix behavior of ResultSet#relative when crossing result set boundaries @@ -944,7 +944,7 @@ With server with version MariaDB 10.2, MySQL 5.7, ensure driver state : - driver does now always get current database, even database is changed by query. - when using rewriteBatchedStatements does return correct autoincrement ids even when session variable - @auto_increment_increment has change during session. + @auto_increment_increment has change during session. ##= CONJ-393 : improve setQueryTimeout to use SET STATEMENT max_statement_time @@ -1012,7 +1012,7 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-440 : handle very big COM_STMT_SEND_LONG_DATA packet (1Gb) * CONJ-429 : ResultSet.getDouble/getFloat may throw a NumberFormatException * CONJ-438 : using option rewriteBatchedStatements, permit rewrite when query has column/table that contain 'select' - keyword. + keyword. ## 1.5.8 @@ -1061,7 +1061,7 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-363 : Connection.getClientInfo implementation correction to follow JDBC rules * CONJ-361 : PrepareStatement setString() with empty string correction. * CONJ-360 : replacing ManagementFactory.getRuntimeMXBean() that cause possible slow connection depending on JVM / - environment + environment * CONJ-359 : Metadata getColumns(...) resultSet doesnt have "IS_GENERATEDCOLUMN" info ## 1.5.3 @@ -1133,7 +1133,7 @@ use the new replicas. ### Bugfix * CONJ-329 and CONJ-330 : rewriteBatchedStatements execute single query exceptions correction. -

    +

    ## 1.5.0 @@ -1146,8 +1146,8 @@ CONJ-295.
    Java kerberos implementation is not well implemented with windows : * need a Windows registry entry ( - HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTGTSessionKey) so windows shared - current ticket to java. + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTGTSessionKey) so windows shared + current ticket to java. * java kinit must be executed to create a Ticket. * restriction when client with local admin rights * ... @@ -1190,13 +1190,13 @@ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
    / Different performance improvement have been done : * Using PreparedStatement on client side use a simple query parser to identify query parameters. This parsing was taking - up to 7% of query time, reduced to 3%. + up to 7% of query time, reduced to 3%. * Better UTF-8 decoding avoiding memory consumption and gain 1-2% query time for big String. * client parsing optimization : rewriteBatchedStatements (insert into ab (i) values (1) and insert into ab (i) values ( - 2) rewritten as insert into ab (i) values (1), (2)) - is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to - contain - query). + 2) rewritten as insert into ab (i) values (1), (2)) + is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to + contain + query). * there was some memory wastage when query return big resultset (> 10kb), slowing query. * ... @@ -1249,9 +1249,9 @@ query [LOAD DATA INFILE](https://mariadb.com/kb/en/mariadb/load-data-infile/).
    Problem is using "LOAD DATA LOCAL INFILE" (ie : loading a file from client), may be a security problem : * A "man in the middle" proxy server can change the actual file asked from server so client will send a Local file to - this proxy. + this proxy. * If someone has can execute query from client, he can have access to any file on client (according to the rights of the - user running the client process). + user running the client process). See [load-data-infile documentation](./documentation/use-mariadb-connector-j-driver.creole#load-data-infile) for more information. @@ -1261,7 +1261,7 @@ Those interceptors: * Must implement interface {{{org.mariadb.jdbc.LocalInfileInterceptor}}}. * Use [[http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html|ServiceLoader]] implementation, so - interceptors classes must be listed in file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor. + interceptors classes must be listed in file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor. Example: {{{ @@ -1306,7 +1306,7 @@ return filePath.equals("/var/tmp/exchanges"); * CONJ-316 : Wrong Exception thrown for ScrollType TYPE_SCROLL_INSENSITIVE * CONJ-298 : Error on Callable function exception when no parameter and space before parenthesis * CONJ-314 : Permit using Call with Statement / Prepare Statement -


    +


    ## 1.4.6 @@ -1346,7 +1346,7 @@ return filePath.equals("/var/tmp/exchanges"); * CONJ-270] permit 65535 parameters to server preparedStatement * CONJ-268] update license header * misc] when option rewriteBatchedStatements is set to true, correction of packet separation when query size > - max_allow_packet + max_allow_packet * misc] performance improvement for select result. ## 1.4.0 @@ -1417,10 +1417,10 @@ select * from performance_schema.session_connect_attrs where processList_id = 5 * CONJ-210 : adding a "jdbcCompliantTruncation" option to force truncation warning as SQLException. * CONJ-211 : when in master/slave configuration, option "assureReadOnly" will ensure that slaves are in read-only mode ( - forcing transaction by a query "SET SESSION TRANSACTION READ ONLY"). + forcing transaction by a query "SET SESSION TRANSACTION READ ONLY"). * CONJ-213 : new option "continueBatchOnError". Permit to continue batch when an exception occur : When executing a - batch and an error occur, must the batch stop immediatly (default) or finish remaining batch before throwing - exception. + batch and an error occur, must the batch stop immediatly (default) or finish remaining batch before throwing + exception. ## Bugfix diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 38304031e..8dc2bff4a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,8 +14,8 @@ them on your own before continuing. * At least one GPG Key see https://help.github.com/en/articles/generating-a-new-gpg-key * [Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) ( - with [JCE policies](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) if using - TLS/SSL) + with [JCE policies](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) if using + TLS/SSL) * IDE (eclipse / netbean / intelliJ) with maven and GIT plugins # Fork source @@ -69,7 +69,7 @@ parameters : jdk: * oraclejdk8 - and if your work is on develop-jre6 branch + and if your work is on develop-jre6 branch * openjdk6 * openjdk7 diff --git a/pom.xml b/pom.xml index cdf810d97..925998a5b 100644 --- a/pom.xml +++ b/pom.xml @@ -247,9 +247,6 @@ *.md .gitignore - - Ed25519*.java - @@ -263,11 +260,8 @@ src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/**/*.java + src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java - - src/main/java/**/*.java - src/test/java/**/*.java - 1.18.1 diff --git a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java index 57ef7a43c..4be6a9690 100644 --- a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java +++ b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java @@ -1386,17 +1386,17 @@ public String getIdentifierQuoteString() { @Override public String getSQLKeywords() { return "ACCESSIBLE,ANALYZE,ASENSITIVE,BEFORE,BIGINT,BINARY,BLOB,CALL,CHANGE,CONDITION,DATABASE,DATABASES," - + "DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DETERMINISTIC,DISTINCTROW,DIV,DUAL,EACH," - + "ELSEIF,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERAL,HIGH_PRIORITY," - + "HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,IGNORE_SERVER_IDS,INDEX,INFILE,INOUT,INT1,INT2," - + "INT3,INT4,INT8,ITERATE,KEY,KEYS,KILL,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCALTIME,LOCALTIMESTAMP,LOCK," - + "LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_HEARTBEAT_PERIOD,MASTER_SSL_VERIFY_SERVER_CERT," - + "MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,MOD,MODIFIES," - + "NO_WRITE_TO_BINLOG,OPTIMIZE,OPTIONALLY,OUT,OUTFILE,PURGE,RANGE,READ_WRITE,READS,REGEXP,RELEASE," - + "RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RETURN,RLIKE,SCHEMAS,SECOND_MICROSECOND,SENSITIVE," - + "SEPARATOR,SHOW,SIGNAL,SLOW,SPATIAL,SPECIFIC,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT," - + "SQLEXCEPTION,SSL,STARTING,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,TRIGGER,UNDO,UNLOCK," - + "UNSIGNED,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,WHILE,XOR,YEAR_MONTH,ZEROFILL"; + + "DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DETERMINISTIC,DISTINCTROW,DIV,DUAL,EACH," + + "ELSEIF,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERAL,HIGH_PRIORITY," + + "HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,IGNORE_SERVER_IDS,INDEX,INFILE,INOUT,INT1,INT2," + + "INT3,INT4,INT8,ITERATE,KEY,KEYS,KILL,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCALTIME,LOCALTIMESTAMP,LOCK," + + "LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_HEARTBEAT_PERIOD,MASTER_SSL_VERIFY_SERVER_CERT," + + "MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,MOD,MODIFIES," + + "NO_WRITE_TO_BINLOG,OPTIMIZE,OPTIONALLY,OUT,OUTFILE,PURGE,RANGE,READ_WRITE,READS,REGEXP,RELEASE," + + "RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RETURN,RLIKE,SCHEMAS,SECOND_MICROSECOND,SENSITIVE," + + "SEPARATOR,SHOW,SIGNAL,SLOW,SPATIAL,SPECIFIC,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT," + + "SQLEXCEPTION,SSL,STARTING,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,TRIGGER,UNDO,UNLOCK," + + "UNSIGNED,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,WHILE,XOR,YEAR_MONTH,ZEROFILL"; } /** @@ -1407,7 +1407,7 @@ public String getSQLKeywords() { @Override public String getNumericFunctions() { return "DIV,ABS,ACOS,ASIN,ATAN,ATAN2,CEIL,CEILING,CONV,COS,COT,CRC32,DEGREES,EXP,FLOOR,GREATEST,LEAST,LN,LOG," - + "LOG10,LOG2,MOD,OCT,PI,POW,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE"; + + "LOG10,LOG2,MOD,OCT,PI,POW,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE"; } /** @@ -1418,11 +1418,11 @@ public String getNumericFunctions() { @Override public String getStringFunctions() { return "ASCII,BIN,BIT_LENGTH,CAST,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONVERT,ELT,EXPORT_SET," - + "EXTRACTVALUE,FIELD,FIND_IN_SET,FORMAT,FROM_BASE64,HEX,INSTR,LCASE,LEFT,LENGTH,LIKE,LOAD_FILE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH" - + " AGAINST,MID,NOT LIKE,NOT" - + " REGEXP,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SOUNDS" - + " LIKE,SPACE,STRCMP,SUBSTR,SUBSTRING," - + "SUBSTRING_INDEX,TO_BASE64,TRIM,UCASE,UNHEX,UPDATEXML,UPPER,WEIGHT_STRING"; + + "EXTRACTVALUE,FIELD,FIND_IN_SET,FORMAT,FROM_BASE64,HEX,INSTR,LCASE,LEFT,LENGTH,LIKE,LOAD_FILE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH" + + " AGAINST,MID,NOT LIKE,NOT" + + " REGEXP,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SOUNDS" + + " LIKE,SPACE,STRCMP,SUBSTR,SUBSTRING," + + "SUBSTRING_INDEX,TO_BASE64,TRIM,UCASE,UNHEX,UPDATEXML,UPPER,WEIGHT_STRING"; } /** @@ -1443,11 +1443,11 @@ public String getSystemFunctions() { @Override public String getTimeDateFunctions() { return "ADDDATE,ADDTIME,CONVERT_TZ,CURDATE,CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURTIME,DATEDIFF," - + "DATE_ADD,DATE_FORMAT,DATE_SUB,DAY,DAYNAME,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,EXTRACT,FROM_DAYS," - + "FROM_UNIXTIME,GET_FORMAT,HOUR,LAST_DAY,LOCALTIME,LOCALTIMESTAMP,MAKEDATE,MAKETIME,MICROSECOND," - + "MINUTE,MONTH,MONTHNAME,NOW,PERIOD_ADD,PERIOD_DIFF,QUARTER,SECOND,SEC_TO_TIME,STR_TO_DATE,SUBDATE," - + "SUBTIME,SYSDATE,TIMEDIFF,TIMESTAMPADD,TIMESTAMPDIFF,TIME_FORMAT,TIME_TO_SEC,TO_DAYS,TO_SECONDS," - + "UNIX_TIMESTAMP,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,WEEK,WEEKDAY,WEEKOFYEAR,YEAR,YEARWEEK"; + + "DATE_ADD,DATE_FORMAT,DATE_SUB,DAY,DAYNAME,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,EXTRACT,FROM_DAYS," + + "FROM_UNIXTIME,GET_FORMAT,HOUR,LAST_DAY,LOCALTIME,LOCALTIMESTAMP,MAKEDATE,MAKETIME,MICROSECOND," + + "MINUTE,MONTH,MONTHNAME,NOW,PERIOD_ADD,PERIOD_DIFF,QUARTER,SECOND,SEC_TO_TIME,STR_TO_DATE,SUBDATE," + + "SUBTIME,SYSDATE,TIMEDIFF,TIMESTAMPADD,TIMESTAMPDIFF,TIME_FORMAT,TIME_TO_SEC,TO_DAYS,TO_SECONDS," + + "UNIX_TIMESTAMP,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,WEEK,WEEKDAY,WEEKOFYEAR,YEAR,YEARWEEK"; } public String getSearchStringEscape() { diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java index 4e85e97df..3122a7484 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java @@ -203,6 +203,8 @@ public void shutdownOutput() { /** Socket address */ public static class SockAddr extends Structure { + /** socket family */ + public short sun_family = AF_UNIX; /** pathname */ public byte[] sun_path; @@ -214,6 +216,7 @@ public static class SockAddr extends Structure { */ @SuppressWarnings({"this-escape"}) public SockAddr(String sunPath) { + byte[] arr = sunPath.getBytes(); sun_path = new byte[arr.length + 1]; System.arraycopy(arr, 0, sun_path, 0, Math.min(sun_path.length - 1, arr.length)); diff --git a/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java b/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java index 9d72293c3..3f54bc793 100644 --- a/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java +++ b/src/main/java/org/mariadb/jdbc/util/ThreadUtils.java @@ -8,7 +8,8 @@ public class ThreadUtils { public static long getId(Thread thread) { - // must be return thread.threadId() for java 19+, but since we support java 8, cannot be removed for now + // must be return thread.threadId() for java 19+, + // but since we support java 8, cannot be removed for now return thread.getId(); } From 10a1107108ddd4b809cf6e48d3f8873e0e3257f2 Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 12:07:14 +0200 Subject: [PATCH 15/26] [CONJ-1116] Avoid unnecessary synchronization on calendar when no calendar parameter --- .../jdbc/client/column/DateColumn.java | 35 +++++++++-- .../jdbc/client/column/StringColumn.java | 60 ++++++++++++++----- .../jdbc/client/column/TimeColumn.java | 24 +++++++- .../jdbc/client/column/TimestampColumn.java | 31 +++++++--- .../jdbc/client/column/YearColumn.java | 23 +++++-- .../mariadb/jdbc/plugin/codec/DateCodec.java | 13 +++- .../mariadb/jdbc/plugin/codec/TimeCodec.java | 26 +++++++- .../jdbc/plugin/codec/TimestampCodec.java | 27 ++++++++- 8 files changed, 197 insertions(+), 42 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java b/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java index 219988d78..d51ecaa34 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java @@ -187,13 +187,22 @@ public Date decodeDateText(ReadableByteBuf buf, MutableInt length, Calendar cal) return null; } - Calendar c = cal == null ? Calendar.getInstance() : cal; - synchronized (c) { + if (cal == null) { + Calendar c = Calendar.getInstance(); c.clear(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); return new Date(c.getTimeInMillis()); + } else { + synchronized (cal) { + cal.clear(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); + return new Date(cal.getTimeInMillis()); + } + } } @@ -205,13 +214,21 @@ public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar ca return null; } - Calendar c = cal == null ? Calendar.getInstance() : cal; - synchronized (c) { + if (cal == null) { + Calendar c = Calendar.getInstance(); c.clear(); c.set(Calendar.YEAR, buf.readShort()); c.set(Calendar.MONTH, buf.readByte() - 1); c.set(Calendar.DAY_OF_MONTH, buf.readByte()); return new Date(c.getTimeInMillis()); + } else { + synchronized (cal) { + cal.clear(); + cal.set(Calendar.YEAR, buf.readShort()); + cal.set(Calendar.MONTH, buf.readByte() - 1); + cal.set(Calendar.DAY_OF_MONTH, buf.readByte()); + return new Date(cal.getTimeInMillis()); + } } } @@ -260,7 +277,6 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C return null; } - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int year; int month; long dayOfMonth; @@ -275,10 +291,17 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C } Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, (int) dayOfMonth, 0, 0, 0); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, (int) dayOfMonth, 0, 0, 0); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos(0); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java b/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java index 6817c51be..80e90eb29 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java @@ -259,13 +259,21 @@ public Date decodeDateText(ReadableByteBuf buf, MutableInt length, Calendar cal) int year = Integer.parseInt(stDatePart[0]); int month = Integer.parseInt(stDatePart[1]); int dayOfMonth = Integer.parseInt(stDatePart[2]); - Calendar c = cal == null ? Calendar.getInstance() : cal; - synchronized (c) { + if (cal == null) { + Calendar c = Calendar.getInstance(); c.clear(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); return new Date(c.getTimeInMillis()); + } else { + synchronized (cal) { + cal.clear(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); + return new Date(cal.getTimeInMillis()); + } } } catch (NumberFormatException nfe) { @@ -296,27 +304,45 @@ public Time decodeTimeText(ReadableByteBuf buf, MutableInt length, Calendar cal) @Override public Time decodeTimeBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int[] parts = LocalTimeCodec.parseTime(buf, length, this); Time t; // specific case for TIME, to handle value not in 00:00:00-23:59:59 - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setLenient(true); if (parts[0] == -1) { cal.set( - 1970, - Calendar.JANUARY, - 1, - parts[0] * parts[1], - parts[0] * parts[2], - parts[0] * parts[3] - 1); + 1970, + Calendar.JANUARY, + 1, + parts[0] * parts[1], + parts[0] * parts[2], + parts[0] * parts[3] - 1); t = new Time(cal.getTimeInMillis() + (1000 - parts[4])); } else { cal.set(1970, Calendar.JANUARY, 1, parts[1], parts[2], parts[3]); t = new Time(cal.getTimeInMillis() + parts[4] / 1_000_000); } + } else { + synchronized (calParam) { + calParam.clear(); + calParam.setLenient(true); + if (parts[0] == -1) { + calParam.set( + 1970, + Calendar.JANUARY, + 1, + parts[0] * parts[1], + parts[0] * parts[2], + parts[0] * parts[3] - 1); + t = new Time(calParam.getTimeInMillis() + (1000 - parts[4])); + } else { + calParam.set(1970, Calendar.JANUARY, 1, parts[1], parts[2], parts[3]); + t = new Time(calParam.getTimeInMillis() + parts[4] / 1_000_000); + } + } } return t; } @@ -378,7 +404,6 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal timestampsPart[4], timestampsPart[5]); timestamp = new Timestamp(c.getTime().getTime()); - timestamp.setNanos(timestampsPart[6] * 1000); } else { synchronized (calParam) { calParam.clear(); @@ -390,17 +415,15 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal timestampsPart[4], timestampsPart[5]); timestamp = new Timestamp(calParam.getTime().getTime()); - timestamp.setNanos(timestampsPart[6] * 1000); } } + timestamp.setNanos(timestampsPart[6] * 1000); return timestamp; } @Override public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - String val = buf.readString(length.get()); try { int[] parts = LocalDateTimeCodec.parseTimestamp(val); @@ -416,10 +439,17 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C int seconds = parts[5]; int microseconds = parts[6] / 1000; Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, dayOfMonth, hour, minutes, seconds); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, dayOfMonth, hour, minutes, seconds); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos(microseconds * 1000); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java b/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java index 29bb30d6e..0844788ce 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java @@ -316,8 +316,8 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal Timestamp t; // specific case for TIME, to handle value not in 00:00:00-23:59:59 - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setLenient(true); if (parts[0] == -1) { @@ -335,6 +335,26 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal t = new Timestamp(cal.getTimeInMillis()); t.setNanos(parts[4]); } + } else { + synchronized (calParam) { + calParam.clear(); + calParam.setLenient(true); + if (parts[0] == -1) { + calParam.set( + 1970, + Calendar.JANUARY, + 1, + parts[0] * parts[1], + parts[0] * parts[2], + parts[0] * parts[3] - 1); + t = new Timestamp(calParam.getTimeInMillis()); + t.setNanos(1_000_000_000 - parts[4]); + } else { + calParam.set(1970, Calendar.JANUARY, 1, parts[1], parts[2], parts[3]); + t = new Timestamp(calParam.getTimeInMillis()); + t.setNanos(parts[4]); + } + } } return t; } diff --git a/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java b/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java index 1be927ffe..e640b22aa 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java @@ -296,8 +296,6 @@ public Date decodeDateText(ReadableByteBuf buf, MutableInt length, Calendar cal) @Override public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - if (length.get() == 0) { length.set(NULL_LENGTH); return null; @@ -333,10 +331,17 @@ public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar ca } Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, dayOfMonth, hour, minutes, seconds); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, dayOfMonth, hour, minutes, seconds); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos((int) (microseconds * 1000)); String st = timestamp.toString(); @@ -361,7 +366,6 @@ public Time decodeTimeBinary(ReadableByteBuf buf, MutableInt length, Calendar ca length.set(NULL_LENGTH); return null; } - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int year = buf.readUnsignedShort(); int month = buf.readByte(); @@ -387,10 +391,17 @@ public Time decodeTimeBinary(ReadableByteBuf buf, MutableInt length, Calendar ca return null; } - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(1970, Calendar.JANUARY, 1, hour, minutes, seconds); return new Time(cal.getTimeInMillis() + microseconds / 1_000); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(1970, Calendar.JANUARY, 1, hour, minutes, seconds); + return new Time(calParam.getTimeInMillis() + microseconds / 1_000); + } } } @@ -476,7 +487,6 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C length.set(NULL_LENGTH); return null; } - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int year = buf.readUnsignedShort(); int month = buf.readByte(); @@ -508,10 +518,17 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C return null; } Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, dayOfMonth, hour, minutes, seconds); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, dayOfMonth, hour, minutes, seconds); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos((int) (microseconds * 1000)); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java b/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java index 659794a24..e7127b54e 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java @@ -121,30 +121,41 @@ public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar ca @Override public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal1 = calParam == null ? Calendar.getInstance() : calParam; - int year = Integer.parseInt(buf.readAscii(length.get())); if (columnLength <= 2) year += year >= 70 ? 1900 : 2000; - synchronized (cal1) { + + if (calParam == null) { + Calendar cal1 = Calendar.getInstance(); cal1.clear(); cal1.set(year, Calendar.JANUARY, 1); return new Timestamp(cal1.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, Calendar.JANUARY, 1); + return new Timestamp(calParam.getTimeInMillis()); + } } } @Override public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - int year = buf.readUnsignedShort(); if (columnLength <= 2) year += year >= 70 ? 1900 : 2000; Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, 0, 1, 0, 0, 0); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, 0, 1, 0, 0, 0); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos(0); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java index 110dda3fc..b8635a22f 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java @@ -79,14 +79,23 @@ public void encodeText( @Override public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength) throws IOException { - Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal; - synchronized (cal) { + if (providedCal == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setTimeInMillis(((java.util.Date) value).getTime()); encoder.writeByte(4); // length encoder.writeShort((short) cal.get(Calendar.YEAR)); encoder.writeByte(((cal.get(Calendar.MONTH) + 1) & 0xff)); encoder.writeByte((cal.get(Calendar.DAY_OF_MONTH) & 0xff)); + } else { + synchronized (providedCal) { + providedCal.clear(); + providedCal.setTimeInMillis(((java.util.Date) value).getTime()); + encoder.writeByte(4); // length + encoder.writeShort((short) providedCal.get(Calendar.YEAR)); + encoder.writeByte(((providedCal.get(Calendar.MONTH) + 1) & 0xff)); + encoder.writeByte((providedCal.get(Calendar.DAY_OF_MONTH) & 0xff)); + } } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java index 1c7c1643f..78a72077c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java @@ -83,8 +83,8 @@ public void encodeText( @Override public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength) throws IOException { - Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal; - synchronized (cal) { + if (providedCal == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setTime((Time) value); cal.set(Calendar.DAY_OF_MONTH, 1); @@ -104,6 +104,28 @@ public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Lon encoder.writeByte((byte) cal.get(Calendar.MINUTE)); encoder.writeByte((byte) cal.get(Calendar.SECOND)); } + } else { + synchronized (providedCal) { + providedCal.clear(); + providedCal.setTime((Time) value); + providedCal.set(Calendar.DAY_OF_MONTH, 1); + if (providedCal.get(Calendar.MILLISECOND) > 0) { + encoder.writeByte((byte) 12); + encoder.writeByte((byte) 0); + encoder.writeInt(0); + encoder.writeByte((byte) providedCal.get(Calendar.HOUR_OF_DAY)); + encoder.writeByte((byte) providedCal.get(Calendar.MINUTE)); + encoder.writeByte((byte) providedCal.get(Calendar.SECOND)); + encoder.writeInt(providedCal.get(Calendar.MILLISECOND) * 1000); + } else { + encoder.writeByte((byte) 8); // length + encoder.writeByte((byte) 0); + encoder.writeInt(0); + encoder.writeByte((byte) providedCal.get(Calendar.HOUR_OF_DAY)); + encoder.writeByte((byte) providedCal.get(Calendar.MINUTE)); + encoder.writeByte((byte) providedCal.get(Calendar.SECOND)); + } + } } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java index 841d505de..5446175e8 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimestampCodec.java @@ -93,8 +93,8 @@ public void encodeText( public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength) throws IOException { Timestamp ts = (Timestamp) value; - Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal; - synchronized (cal) { + if (providedCal == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setTimeInMillis(ts.getTime()); if (ts.getNanos() == 0) { @@ -115,6 +115,29 @@ public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Lon encoder.writeByte(cal.get(Calendar.SECOND)); encoder.writeInt(ts.getNanos() / 1000); } + } else { + synchronized (providedCal) { + providedCal.clear(); + providedCal.setTimeInMillis(ts.getTime()); + if (ts.getNanos() == 0) { + encoder.writeByte(7); // length + encoder.writeShort((short) providedCal.get(Calendar.YEAR)); + encoder.writeByte((providedCal.get(Calendar.MONTH) + 1)); + encoder.writeByte(providedCal.get(Calendar.DAY_OF_MONTH)); + encoder.writeByte(providedCal.get(Calendar.HOUR_OF_DAY)); + encoder.writeByte(providedCal.get(Calendar.MINUTE)); + encoder.writeByte(providedCal.get(Calendar.SECOND)); + } else { + encoder.writeByte(11); // length + encoder.writeShort((short) providedCal.get(Calendar.YEAR)); + encoder.writeByte((providedCal.get(Calendar.MONTH) + 1)); + encoder.writeByte(providedCal.get(Calendar.DAY_OF_MONTH)); + encoder.writeByte(providedCal.get(Calendar.HOUR_OF_DAY)); + encoder.writeByte(providedCal.get(Calendar.MINUTE)); + encoder.writeByte(providedCal.get(Calendar.SECOND)); + encoder.writeInt(ts.getNanos() / 1000); + } + } } } From a17728532a889beda573b500bb2ebf97499bbabc Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 12:15:32 +0200 Subject: [PATCH 16/26] [CONJ-1115] Make connector become virtual-thread friendly --- .../jdbc/client/impl/StandardClient.java | 6 +- .../socket/impl/CompressInputStream.java | 60 +++++++++----- .../socket/impl/ReadAheadBufferedStream.java | 82 +++++++++++-------- 3 files changed, 93 insertions(+), 55 deletions(-) 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 1a0caa53d..451dbf4ba 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java @@ -107,7 +107,7 @@ public StandardClient( OutputStream out = new BufferedOutputStream(socket.getOutputStream(), 16384); InputStream in = conf.useReadAheadInput() - ? new ReadAheadBufferedStream(socket.getInputStream()) + ? new ReadAheadBufferedStream(socket.getInputStream(), lock) : new BufferedInputStream(socket.getInputStream(), 16384); assignStream(out, in, conf, null); @@ -165,7 +165,7 @@ public StandardClient( out = new BufferedOutputStream(sslSocket.getOutputStream(), 16384); in = conf.useReadAheadInput() - ? new ReadAheadBufferedStream(sslSocket.getInputStream()) + ? new ReadAheadBufferedStream(sslSocket.getInputStream(), lock) : new BufferedInputStream(sslSocket.getInputStream(), 16384); assignStream(out, in, conf, handshake.getThreadId()); } @@ -199,7 +199,7 @@ public StandardClient( if ((clientCapabilities & Capabilities.COMPRESS) != 0) { assignStream( new CompressOutputStream(out, compressionSequence), - new CompressInputStream(in, compressionSequence), + new CompressInputStream(in, compressionSequence, lock), conf, handshake.getThreadId()); } diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java index e8515e9a7..f07781583 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java @@ -6,6 +6,7 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.util.concurrent.locks.ReentrantLock; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import org.mariadb.jdbc.client.util.MutableByte; @@ -22,7 +23,8 @@ public class CompressInputStream extends InputStream { private int end; private int pos; - private byte[] buf; + private volatile byte[] buf; + private final ReentrantLock lock; /** * Constructor. When this handler is used, driver expect packet with 7 byte compression header @@ -30,9 +32,10 @@ public class CompressInputStream extends InputStream { * @param in socket input stream * @param compressionSequence compression sequence */ - public CompressInputStream(InputStream in, MutableByte compressionSequence) { + public CompressInputStream(InputStream in, MutableByte compressionSequence, ReentrantLock lock) { this.in = in; this.sequence = compressionSequence; + this.lock = lock; } /** @@ -87,19 +90,23 @@ public int read(byte[] b, int off, int len) throws IOException { } int totalReads = 0; + lock.lock(); + try { + do { + if (end - pos <= 0) { + retrieveBuffer(); + } + // copy internal value to buf. + int copyLength = Math.min(len - totalReads, end - pos); + System.arraycopy(buf, pos, b, off + totalReads, copyLength); + pos += copyLength; + totalReads += copyLength; + } while (totalReads < len && super.available() > 0); - do { - if (end - pos <= 0) { - retrieveBuffer(); - } - // copy internal value to buf. - int copyLength = Math.min(len - totalReads, end - pos); - System.arraycopy(buf, pos, b, off + totalReads, copyLength); - pos += copyLength; - totalReads += copyLength; - } while (totalReads < len && super.available() > 0); - - return totalReads; + return totalReads; + } finally { + lock.unlock(); + } } private void retrieveBuffer() throws IOException { @@ -218,7 +225,12 @@ public long skip(long n) throws IOException { */ @Override public int available() throws IOException { - return in.available(); + lock.lock(); + try { + return in.available(); + } finally { + lock.unlock(); + } } /** @@ -257,8 +269,13 @@ public void close() throws IOException { * @see InputStream#reset() */ @Override - public synchronized void mark(int readlimit) { - in.mark(readlimit); + public void mark(int readlimit) { + lock.lock(); + try { + in.mark(readlimit); + } finally { + lock.unlock(); + } } /** @@ -299,8 +316,13 @@ public synchronized void mark(int readlimit) { * @see IOException */ @Override - public synchronized void reset() throws IOException { - in.reset(); + public void reset() throws IOException { + lock.lock(); + try { + in.reset(); + } finally { + lock.unlock(); + } } /** diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java index bcdbb5770..c0cdc64f2 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java @@ -6,6 +6,7 @@ import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.concurrent.locks.ReentrantLock; /** * Permit to buf socket data, reading not only asked bytes, but available number of bytes when @@ -15,6 +16,7 @@ public class ReadAheadBufferedStream extends FilterInputStream { private static final int BUF_SIZE = 16384; private final byte[] buf; + private final ReentrantLock lock; private int end; private int pos; @@ -23,11 +25,16 @@ public class ReadAheadBufferedStream extends FilterInputStream { * * @param in socket input stream */ - public ReadAheadBufferedStream(InputStream in) { + public ReadAheadBufferedStream(InputStream in, ReentrantLock lock) { super(in); buf = new byte[BUF_SIZE]; end = 0; pos = 0; + this.lock = lock; + } + + public ReentrantLock getLock() { + return lock; } /** @@ -39,45 +46,49 @@ public ReadAheadBufferedStream(InputStream in) { * @return number of added bytes * @throws IOException if exception during socket reading */ - public synchronized int read(byte[] externalBuf, int off, int len) throws IOException { + public int read(byte[] externalBuf, int off, int len) throws IOException { if (len == 0) { return 0; } - - int totalReads = 0; - while (true) { - - // read - if (end - pos <= 0) { - if (len - totalReads >= buf.length) { - // buf length is less than asked byte and buf is empty - // => filling directly into external buf - int reads = super.read(externalBuf, off + totalReads, len - totalReads); - if (reads <= 0) { - return (totalReads == 0) ? -1 : totalReads; - } - return totalReads + reads; - - } else { - - // filling internal buf - fillingBuffer(len - totalReads); - if (end <= 0) { - return (totalReads == 0) ? -1 : totalReads; + lock.lock(); + try { + int totalReads = 0; + while (true) { + + // read + if (end - pos <= 0) { + if (len - totalReads >= buf.length) { + // buf length is less than asked byte and buf is empty + // => filling directly into external buf + int reads = super.read(externalBuf, off + totalReads, len - totalReads); + if (reads <= 0) { + return (totalReads == 0) ? -1 : totalReads; + } + return totalReads + reads; + + } else { + + // filling internal buf + fillingBuffer(len - totalReads); + if (end <= 0) { + return (totalReads == 0) ? -1 : totalReads; + } } } - } - // copy internal value to buf. - int copyLength = Math.min(len - totalReads, end - pos); - System.arraycopy(buf, pos, externalBuf, off + totalReads, copyLength); - pos += copyLength; - totalReads += copyLength; + // copy internal value to buf. + int copyLength = Math.min(len - totalReads, end - pos); + System.arraycopy(buf, pos, externalBuf, off + totalReads, copyLength); + pos += copyLength; + totalReads += copyLength; - if (totalReads >= len || super.available() <= 0) { - return totalReads; + if (totalReads >= len || super.available() <= 0) { + return totalReads; + } } + } finally{ + lock.unlock(); } } @@ -103,8 +114,13 @@ public void close() throws IOException { pos = 0; } - public synchronized int available() throws IOException { - return end - pos + super.available(); + public int available() throws IOException { + lock.lock(); + try { + return end - pos + super.available(); + } finally { + lock.unlock(); + } } public int read() throws IOException { From db65710106e0302e55bd97d3ffd83661aa1707d0 Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 12:18:18 +0200 Subject: [PATCH 17/26] [misc] update mysql connector in benchmark to recent version (8.1.0) --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 925998a5b..ed7ab587f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ mariadb-java-client jar mariadb-java-client - 3.2.0 + 3.3.0-SNAPSHOT JDBC driver for MariaDB and MySQL https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/ @@ -23,7 +23,7 @@ 1.4.4 0.8.10 3.3.0 - 8.0.31 + 8.1.0 6.3.1 2.40.0 @@ -420,8 +420,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${mysql-connector-java.version} From f5a33b6d8e1540e58ad60b1782e437f20b7aba1a Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 16:03:28 +0200 Subject: [PATCH 18/26] [CONJ-1115] Make connector become virtual-thread friendly - part 2 --- .../jdbc/client/impl/StandardClient.java | 8 +- .../socket/impl/CompressInputStream.java | 55 +++++-------- .../socket/impl/ReadAheadBufferedStream.java | 79 ++++++++----------- 3 files changed, 55 insertions(+), 87 deletions(-) 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 451dbf4ba..04a1e48b2 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java @@ -104,10 +104,10 @@ public StandardClient( // ********************************************************************** // creating socket // ********************************************************************** - OutputStream out = new BufferedOutputStream(socket.getOutputStream(), 16384); + OutputStream out = socket.getOutputStream(); InputStream in = conf.useReadAheadInput() - ? new ReadAheadBufferedStream(socket.getInputStream(), lock) + ? new ReadAheadBufferedStream(socket.getInputStream()) : new BufferedInputStream(socket.getInputStream(), 16384); assignStream(out, in, conf, null); @@ -165,7 +165,7 @@ public StandardClient( out = new BufferedOutputStream(sslSocket.getOutputStream(), 16384); in = conf.useReadAheadInput() - ? new ReadAheadBufferedStream(sslSocket.getInputStream(), lock) + ? new ReadAheadBufferedStream(sslSocket.getInputStream()) : new BufferedInputStream(sslSocket.getInputStream(), 16384); assignStream(out, in, conf, handshake.getThreadId()); } @@ -199,7 +199,7 @@ public StandardClient( if ((clientCapabilities & Capabilities.COMPRESS) != 0) { assignStream( new CompressOutputStream(out, compressionSequence), - new CompressInputStream(in, compressionSequence, lock), + new CompressInputStream(in, compressionSequence), conf, handshake.getThreadId()); } diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java index f07781583..ee39fc18f 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java @@ -24,18 +24,19 @@ public class CompressInputStream extends InputStream { private int end; private int pos; private volatile byte[] buf; - private final ReentrantLock lock; /** * Constructor. When this handler is used, driver expect packet with 7 byte compression header * + * Implementation doesn't use synchronized/semaphore because all used are already locked by + * Statement/PreparedStatement Reentrant lock + * * @param in socket input stream * @param compressionSequence compression sequence */ - public CompressInputStream(InputStream in, MutableByte compressionSequence, ReentrantLock lock) { + public CompressInputStream(InputStream in, MutableByte compressionSequence) { this.in = in; this.sequence = compressionSequence; - this.lock = lock; } /** @@ -90,23 +91,18 @@ public int read(byte[] b, int off, int len) throws IOException { } int totalReads = 0; - lock.lock(); - try { - do { - if (end - pos <= 0) { - retrieveBuffer(); - } - // copy internal value to buf. - int copyLength = Math.min(len - totalReads, end - pos); - System.arraycopy(buf, pos, b, off + totalReads, copyLength); - pos += copyLength; - totalReads += copyLength; - } while (totalReads < len && super.available() > 0); + do { + if (end - pos <= 0) { + retrieveBuffer(); + } + // copy internal value to buf. + int copyLength = Math.min(len - totalReads, end - pos); + System.arraycopy(buf, pos, b, off + totalReads, copyLength); + pos += copyLength; + totalReads += copyLength; + } while (totalReads < len && super.available() > 0); - return totalReads; - } finally { - lock.unlock(); - } + return totalReads; } private void retrieveBuffer() throws IOException { @@ -225,12 +221,7 @@ public long skip(long n) throws IOException { */ @Override public int available() throws IOException { - lock.lock(); - try { - return in.available(); - } finally { - lock.unlock(); - } + return in.available(); } /** @@ -270,12 +261,7 @@ public void close() throws IOException { */ @Override public void mark(int readlimit) { - lock.lock(); - try { - in.mark(readlimit); - } finally { - lock.unlock(); - } + in.mark(readlimit); } /** @@ -317,12 +303,7 @@ public void mark(int readlimit) { */ @Override public void reset() throws IOException { - lock.lock(); - try { - in.reset(); - } finally { - lock.unlock(); - } + in.reset(); } /** diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java index c0cdc64f2..76b0bab93 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java @@ -16,25 +16,22 @@ public class ReadAheadBufferedStream extends FilterInputStream { private static final int BUF_SIZE = 16384; private final byte[] buf; - private final ReentrantLock lock; private int end; private int pos; /** * Constructor * + * Implementation doesn't use synchronized/semaphore because all used are already locked by + * Statement/PreparedStatement Reentrant lock + * * @param in socket input stream */ - public ReadAheadBufferedStream(InputStream in, ReentrantLock lock) { + public ReadAheadBufferedStream(InputStream in) { super(in); buf = new byte[BUF_SIZE]; end = 0; pos = 0; - this.lock = lock; - } - - public ReentrantLock getLock() { - return lock; } /** @@ -51,44 +48,39 @@ public int read(byte[] externalBuf, int off, int len) throws IOException { if (len == 0) { return 0; } - lock.lock(); - try { - int totalReads = 0; - while (true) { - - // read - if (end - pos <= 0) { - if (len - totalReads >= buf.length) { - // buf length is less than asked byte and buf is empty - // => filling directly into external buf - int reads = super.read(externalBuf, off + totalReads, len - totalReads); - if (reads <= 0) { - return (totalReads == 0) ? -1 : totalReads; - } - return totalReads + reads; - - } else { - - // filling internal buf - fillingBuffer(len - totalReads); - if (end <= 0) { - return (totalReads == 0) ? -1 : totalReads; - } + int totalReads = 0; + while (true) { + + // read + if (end - pos <= 0) { + if (len - totalReads >= buf.length) { + // buf length is less than asked byte and buf is empty + // => filling directly into external buf + int reads = super.read(externalBuf, off + totalReads, len - totalReads); + if (reads <= 0) { + return (totalReads == 0) ? -1 : totalReads; } - } + return totalReads + reads; - // copy internal value to buf. - int copyLength = Math.min(len - totalReads, end - pos); - System.arraycopy(buf, pos, externalBuf, off + totalReads, copyLength); - pos += copyLength; - totalReads += copyLength; + } else { - if (totalReads >= len || super.available() <= 0) { - return totalReads; + // filling internal buf + fillingBuffer(len - totalReads); + if (end <= 0) { + return (totalReads == 0) ? -1 : totalReads; + } } } - } finally{ - lock.unlock(); + + // copy internal value to buf. + int copyLength = Math.min(len - totalReads, end - pos); + System.arraycopy(buf, pos, externalBuf, off + totalReads, copyLength); + pos += copyLength; + totalReads += copyLength; + + if (totalReads >= len || super.available() <= 0) { + return totalReads; + } } } @@ -115,12 +107,7 @@ public void close() throws IOException { } public int available() throws IOException { - lock.lock(); - try { - return end - pos + super.available(); - } finally { - lock.unlock(); - } + return end - pos + super.available(); } public int read() throws IOException { From be3eb29fe66b67f6237db4f034bc5414f7c412a8 Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 16:03:44 +0200 Subject: [PATCH 19/26] bump jmh version --- pom.xml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ed7ab587f..14c29a753 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ UTF-8 - 1.34 + 1.37 5.8.2 1.5.0 3.22.0 @@ -105,8 +105,8 @@ -Xlint:all,-options,-path,-processing - 1.8 - 1.8 + 21 + 21 @@ -424,7 +424,11 @@ mysql-connector-j ${mysql-connector-java.version} - + + com.zaxxer + HikariCP + 5.0.1 + From c46c6bc0ed5ef14c301ac22760d0b6b5b0e8948f Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 17:47:57 +0200 Subject: [PATCH 20/26] [misc] remove skysql testing --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f1c188c8..657792ba5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,8 +48,6 @@ jobs: - env: srv=build - env: srv=xpand TEST_DB_OTHER="&initSql=SET NAMES UTF8" - env: srv=mariadb-es local=1 - - env: srv=skysql - - env: srv=skysql-ha include: - stage: Minimal env: srv=mariadb v=10.6 packet=8 @@ -75,10 +73,6 @@ jobs: name: "Maxscale" - env: srv=xpand TEST_DB_OTHER="&initSql=SET NAMES UTF8" name: "Xpand" - - env: srv=skysql - name: "SkySQL" - - env: srv=skysql-ha - name: "SkySQL with replication" - stage: Community env: srv=mariadb v=10.6 From 69735a540f25ce5793144c61f9edb810f7d15edf Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 23 Oct 2023 17:48:18 +0200 Subject: [PATCH 21/26] [misc] TemporalField use code simplification --- src/benchmark/java/org/mariadb/jdbc/Do_1.java | 4 +-- .../socket/impl/CompressInputStream.java | 1 - .../socket/impl/ReadAheadBufferedStream.java | 1 - .../jdbc/plugin/codec/InstantCodec.java | 25 +++++++++---------- .../jdbc/plugin/codec/LocalDateCodec.java | 7 +++--- .../jdbc/plugin/codec/LocalDateTimeCodec.java | 25 +++++++++---------- .../jdbc/plugin/codec/LocalTimeCodec.java | 13 +++++----- .../plugin/codec/OffsetDateTimeCodec.java | 25 +++++++++---------- .../jdbc/plugin/codec/ZonedDateTimeCodec.java | 25 +++++++++---------- .../PreparedStatementParametersTest.java | 3 +-- 10 files changed, 59 insertions(+), 70 deletions(-) diff --git a/src/benchmark/java/org/mariadb/jdbc/Do_1.java b/src/benchmark/java/org/mariadb/jdbc/Do_1.java index acdfd8745..96eec41ce 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Do_1.java +++ b/src/benchmark/java/org/mariadb/jdbc/Do_1.java @@ -3,10 +3,8 @@ // Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - -import java.sql.ResultSet; import java.sql.Statement; +import org.openjdk.jmh.annotations.Benchmark; public class Do_1 extends Common { diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java index ee39fc18f..6f96c9330 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java @@ -6,7 +6,6 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; -import java.util.concurrent.locks.ReentrantLock; import java.util.zip.DataFormatException; import java.util.zip.Inflater; import org.mariadb.jdbc.client.util.MutableByte; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java index 76b0bab93..e649b3d0a 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java @@ -6,7 +6,6 @@ import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.concurrent.locks.ReentrantLock; /** * Permit to buf socket data, reading not only asked bytes, but available number of bytes when diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java index 04a002b34..40acfb46a 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java @@ -6,7 +6,6 @@ import java.io.IOException; import java.sql.SQLDataException; import java.time.*; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -104,21 +103,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar calParam, Long m int nano = zonedDateTime.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) zonedDateTime.get(ChronoField.YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(zonedDateTime.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(zonedDateTime.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(zonedDateTime.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) zonedDateTime.getYear()); + encoder.writeByte(zonedDateTime.getMonth().getValue()); + encoder.writeByte(zonedDateTime.getDayOfMonth()); + encoder.writeByte(zonedDateTime.getHour()); + encoder.writeByte(zonedDateTime.getMinute()); + encoder.writeByte(zonedDateTime.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) zonedDateTime.get(ChronoField.YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(zonedDateTime.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(zonedDateTime.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(zonedDateTime.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) zonedDateTime.getYear()); + encoder.writeByte(zonedDateTime.getMonthValue()); + encoder.writeByte(zonedDateTime.getDayOfMonth()); + encoder.writeByte(zonedDateTime.getHour()); + encoder.writeByte(zonedDateTime.getMinute()); + encoder.writeByte(zonedDateTime.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java index 2f9d0f50b..1647af1f9 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java @@ -9,7 +9,6 @@ import java.sql.SQLDataException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -275,9 +274,9 @@ public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Lon throws IOException { LocalDate val = (LocalDate) value; encoder.writeByte(7); // length - encoder.writeShort((short) val.get(ChronoField.YEAR)); - encoder.writeByte(val.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(val.get(ChronoField.DAY_OF_MONTH)); + encoder.writeShort((short) val.getYear()); + encoder.writeByte(val.getMonthValue()); + encoder.writeByte(val.getDayOfMonth()); encoder.writeBytes(new byte[] {0, 0, 0}); } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java index 9407e9b7d..64bd62e80 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java @@ -11,7 +11,6 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -329,21 +328,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar cal, Long maxLen int nano = val.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) val.get(ChronoField.YEAR)); - encoder.writeByte(val.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(val.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) val.getYear()); + encoder.writeByte(val.getMonthValue()); + encoder.writeByte(val.getDayOfMonth()); + encoder.writeByte(val.getHour()); + encoder.writeByte(val.getMinute()); + encoder.writeByte(val.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) val.get(ChronoField.YEAR)); - encoder.writeByte(val.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(val.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) val.getYear()); + encoder.writeByte(val.getMonthValue()); + encoder.writeByte(val.getDayOfMonth()); + encoder.writeByte(val.getHour()); + encoder.writeByte(val.getMinute()); + encoder.writeByte(val.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java index 7a9b9771f..be68219b2 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java @@ -11,7 +11,6 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import java.util.TimeZone; @@ -315,17 +314,17 @@ public void encodeBinary(Writer encoder, Object value, Calendar cal, Long maxLen encoder.writeByte((byte) 12); encoder.writeByte((byte) 0); encoder.writeInt(0); - encoder.writeByte((byte) val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte((byte) val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte((byte) val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeByte((byte) val.getHour()); + encoder.writeByte((byte) val.getMinute()); + encoder.writeByte((byte) val.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 8); encoder.writeByte((byte) 0); encoder.writeInt(0); - encoder.writeByte((byte) val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte((byte) val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte((byte) val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeByte((byte) val.getHour()); + encoder.writeByte((byte) val.getMinute()); + encoder.writeByte((byte) val.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java index 7aadd9bb6..94e0b5738 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java @@ -8,7 +8,6 @@ import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZonedDateTime; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -142,21 +141,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar calParam, Long m int nano = convertedZdt.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) convertedZdt.get(ChronoField.YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(convertedZdt.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(convertedZdt.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(convertedZdt.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) convertedZdt.getYear()); + encoder.writeByte(convertedZdt.getMonthValue()); + encoder.writeByte(convertedZdt.getDayOfMonth()); + encoder.writeByte(convertedZdt.getHour()); + encoder.writeByte(convertedZdt.getMinute()); + encoder.writeByte(convertedZdt.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) convertedZdt.get(ChronoField.YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(convertedZdt.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(convertedZdt.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(convertedZdt.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) convertedZdt.getYear()); + encoder.writeByte(convertedZdt.getMonthValue()); + encoder.writeByte(convertedZdt.getDayOfMonth()); + encoder.writeByte(convertedZdt.getHour()); + encoder.writeByte(convertedZdt.getMinute()); + encoder.writeByte(convertedZdt.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/ZonedDateTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/ZonedDateTimeCodec.java index 54aaad28a..e7d2ef99a 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/ZonedDateTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/ZonedDateTimeCodec.java @@ -7,7 +7,6 @@ import java.sql.SQLDataException; import java.time.LocalDateTime; import java.time.ZonedDateTime; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -96,21 +95,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar calParam, Long m int nano = convertedZdt.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) convertedZdt.get(ChronoField.YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(convertedZdt.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(convertedZdt.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(convertedZdt.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) convertedZdt.getYear()); + encoder.writeByte(convertedZdt.getMonthValue()); + encoder.writeByte(convertedZdt.getDayOfMonth()); + encoder.writeByte(convertedZdt.getHour()); + encoder.writeByte(convertedZdt.getMinute()); + encoder.writeByte(convertedZdt.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) convertedZdt.get(ChronoField.YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(convertedZdt.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(convertedZdt.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(convertedZdt.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) convertedZdt.getYear()); + encoder.writeByte(convertedZdt.getMonthValue()); + encoder.writeByte(convertedZdt.getDayOfMonth()); + encoder.writeByte(convertedZdt.getHour()); + encoder.writeByte(convertedZdt.getMinute()); + encoder.writeByte(convertedZdt.getSecond()); } } diff --git a/src/test/java/org/mariadb/jdbc/integration/PreparedStatementParametersTest.java b/src/test/java/org/mariadb/jdbc/integration/PreparedStatementParametersTest.java index f86b7a418..e21ab3f26 100644 --- a/src/test/java/org/mariadb/jdbc/integration/PreparedStatementParametersTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/PreparedStatementParametersTest.java @@ -225,8 +225,7 @@ public void checkParameters(org.mariadb.jdbc.Connection con, boolean text) throw rs -> assertEquals("abcde", rs.getString(1)), con); final String unicodeString = - "" - + "\uD83D\uDE0E" // 😎 unicode 6 smiling face with sunglasses + "\uD83D\uDE0E" // 😎 unicode 6 smiling face with sunglasses + "\uD83C\uDF36" // 🌶 unicode 7 hot pepper + "\uD83C\uDFA4" // 🎤 unicode 8 no microphones + "\uD83E\uDD42 "; // 🥂 unicode 9 clinking glasses From 8690386197dbf1ea57d12bec56e21c8350a2b563 Mon Sep 17 00:00:00 2001 From: rusher Date: Thu, 26 Oct 2023 15:43:49 +0200 Subject: [PATCH 22/26] [CONJ-1102] BatchUpdateException.getUpdateCounts() wrong results --- .../jdbc/client/impl/StandardClient.java | 3 ++- .../mariadb/jdbc/export/ExceptionFactory.java | 14 +++++++---- .../mariadb/jdbc/integration/BatchTest.java | 23 +++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) 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 04a1e48b2..9d3718c10 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/StandardClient.java @@ -595,6 +595,7 @@ public List executePipeline( return results; } catch (SQLException sqlException) { if (!closed) { + results.add(null); // read remaining results perMsgCounter++; for (; perMsgCounter < responseMsg[readCounter - 1]; perMsgCounter++) { @@ -626,7 +627,7 @@ public List executePipeline( resultSetType, closeOnCompletion)); } catch (SQLException e) { - // eat + results.add(null); } } } diff --git a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java index c0bd6cd1e..1c1f5931b 100644 --- a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java +++ b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java @@ -193,8 +193,6 @@ public BatchUpdateException createBatchUpdate( public BatchUpdateException createBatchUpdate( List res, int length, int[] responseMsg, SQLException sqle) { int[] updateCounts = new int[length]; - - int responseIncrement = 0; for (int i = 0; i < length; i++) { if (i >= responseMsg.length) { Arrays.fill(updateCounts, i, length, Statement.EXECUTE_FAILED); @@ -204,8 +202,16 @@ public BatchUpdateException createBatchUpdate( if (MsgResponseNo < 1) { updateCounts[0] = Statement.EXECUTE_FAILED; return new BatchUpdateException(updateCounts, sqle); - } else if (MsgResponseNo == 1 && res.size() > i && res.get(i) instanceof OkPacket) { - updateCounts[i] = (int) ((OkPacket) res.get(i)).getAffectedRows(); + } else if (MsgResponseNo == 1) { + if (i >= res.size() || res.get(i) == null) { + updateCounts[i] = Statement.EXECUTE_FAILED; + continue; + } + if (res.get(i) instanceof OkPacket) { + updateCounts[i] = (int) ((OkPacket) res.get(i)).getAffectedRows(); + continue; + } + updateCounts[i] = Statement.SUCCESS_NO_INFO; } else { // unknown. updateCounts[i] = Statement.SUCCESS_NO_INFO; diff --git a/src/test/java/org/mariadb/jdbc/integration/BatchTest.java b/src/test/java/org/mariadb/jdbc/integration/BatchTest.java index 5ba617699..5060564bf 100644 --- a/src/test/java/org/mariadb/jdbc/integration/BatchTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/BatchTest.java @@ -31,6 +31,29 @@ public static void after2() throws SQLException { stmt.execute("DROP TABLE IF EXISTS BatchTest"); } + @Test + public void batchError() throws SQLException { + Statement stmt = sharedConn.createStatement(); + stmt.execute("DROP TABLE IF EXISTS t1"); + stmt.execute("CREATE TABLE t1(c0 DATE UNIQUE PRIMARY KEY NOT NULL)"); + + stmt.addBatch("INSERT INTO t1 VALUES ('2006-04-01')"); + stmt.addBatch("INSERT INTO t1 VALUES ('2006-04-01')"); + stmt.addBatch("INSERT INTO t1 VALUES ('2019-04-11')"); + stmt.addBatch("INSERT INTO t1 VALUES ('2006-04-01')"); + stmt.addBatch("INSERT INTO t1 VALUES ('2020-04-11')"); + try { + stmt.executeBatch(); + fail(); + } catch (BatchUpdateException e) { + assertTrue(e.getMessage().contains("Duplicate entry")); + assertEquals(5, e.getUpdateCounts().length); + assertArrayEquals( + new int[] {1, java.sql.Statement.EXECUTE_FAILED, 1, java.sql.Statement.EXECUTE_FAILED, 1}, + e.getUpdateCounts()); + } + } + @Test public void wrongParameter() throws SQLException { try (Connection con = createCon("&useServerPrepStmts=false")) { From 057b2e9d015dbb1d57ca838c1725883c9c03d177 Mon Sep 17 00:00:00 2001 From: rusher Date: Thu, 26 Oct 2023 16:03:49 +0200 Subject: [PATCH 23/26] [misc] default compiler version correction --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 14c29a753..ab1d87565 100644 --- a/pom.xml +++ b/pom.xml @@ -105,8 +105,8 @@ -Xlint:all,-options,-path,-processing - 21 - 21 + 1.8 + 1.8 From 52ab8d38e1f1a405d4f9470b0f72eb8a4ff1b04b Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 6 Nov 2023 11:59:33 +0100 Subject: [PATCH 24/26] [CONJ-1108] Database metadata listing TEMPORARY tables/sequences --- .../org/mariadb/jdbc/DatabaseMetaData.java | 21 ++++++--- .../integration/DatabaseMetadataTest.java | 43 +++++++++++++++++++ .../resultset/ResultSetMetadataTest.java | 8 ++++ 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java index 4be6a9690..f5db93b47 100644 --- a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java +++ b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java @@ -722,7 +722,7 @@ public ResultSet getTables( StringBuilder sb = new StringBuilder( "SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, IF(TABLE_TYPE='BASE" - + " TABLE' or TABLE_TYPE='SYSTEM VERSIONED', 'TABLE', TABLE_TYPE) as TABLE_TYPE," + + " TABLE' or TABLE_TYPE='SYSTEM VERSIONED', 'TABLE', IF(TABLE_TYPE='TEMPORARY', 'LOCAL TEMPORARY', TABLE_TYPE)) as TABLE_TYPE," + " TABLE_COMMENT REMARKS, NULL TYPE_CAT, NULL TYPE_SCHEM, NULL TYPE_NAME, NULL" + " SELF_REFERENCING_COL_NAME, NULL REF_GENERATION FROM" + " INFORMATION_SCHEMA.TABLES"); @@ -744,8 +744,17 @@ public ResultSet getTables( mustAddType = false; continue; } - String type = "TABLE".equals(s) ? "'BASE TABLE','SYSTEM VERSIONED'" : escapeQuote(s); - sqlType.append(type); + switch (s) { + case "TABLE": + sqlType.append("'BASE TABLE','SYSTEM VERSIONED'"); + break; + case "LOCAL TEMPORARY": + sqlType.append("'TEMPORARY'"); + break; + default: + sqlType.append(escapeQuote(s)); + break; + } } sqlType.append(")"); if (mustAddType) sb.append(sqlType); @@ -2382,8 +2391,10 @@ public ResultSet getCatalogs() throws SQLException { public ResultSet getTableTypes() throws SQLException { return executeQuery( - "SELECT 'TABLE' TABLE_TYPE UNION SELECT 'SYSTEM VIEW' TABLE_TYPE UNION SELECT 'VIEW'" - + " TABLE_TYPE"); + "SELECT 'TABLE' TABLE_TYPE " + + "UNION SELECT 'SYSTEM VIEW' TABLE_TYPE " + + "UNION SELECT 'VIEW' TABLE_TYPE " + + "UNION SELECT 'LOCAL TEMPORARY' TABLE_TYPE"); } /** diff --git a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java index f4b9b16c4..f7fa25165 100644 --- a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java @@ -2717,4 +2717,47 @@ public void foreignKeyTest() throws SQLException { } } } + + + @Test + public void testTemporaryTables() throws SQLException { + Assumptions.assumeTrue(isMariaDBServer() && minVersion(11,2,0)); + Assumptions.assumeTrue( + !"mariadb-es".equals(System.getenv("srv")) + && !"mariadb-es-test".equals(System.getenv("srv"))); + + java.sql.Statement stmt = sharedConn.createStatement(); + stmt.execute("create temporary table testTemporaryTables (b int)"); + try (Connection con = createCon()) { + java.sql.Statement ss = con.createStatement(); + ResultSet rr = ss.executeQuery("select table_schema, table_name, table_type, temporary " + + "from information_schema.tables " + + "where TABLE_NAME = 'testTemporaryTables'"); + assertFalse(rr.next()); + } + DatabaseMetaData dbmd = sharedConn.getMetaData(); + + ResultSet rs = dbmd.getTables(null, null, "testTemporary%", null); + assertTrue(rs.next()); + assertEquals("testtemporarytables",rs.getString("TABLE_NAME").toLowerCase()); + assertEquals("LOCAL TEMPORARY", rs.getString("TABLE_TYPE")); + assertFalse(rs.next()); + + rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"LOCAL TEMPORARY"}); + assertTrue(rs.next()); + assertEquals("testtemporarytables",rs.getString("TABLE_NAME").toLowerCase()); + assertEquals("LOCAL TEMPORARY", rs.getString("TABLE_TYPE")); + assertFalse(rs.next()); + + + rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"TEMPORARY"}); + assertTrue(rs.next()); + assertEquals("testtemporarytables",rs.getString("TABLE_NAME").toLowerCase()); + assertEquals("LOCAL TEMPORARY", rs.getString("TABLE_TYPE")); + assertFalse(rs.next()); + + rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"TABLE"}); + assertFalse(rs.next()); + } + } diff --git a/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java b/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java index 5f923ebc2..7c0b3d1d2 100644 --- a/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/resultset/ResultSetMetadataTest.java @@ -244,5 +244,13 @@ public void databaseResultsetMeta() throws SQLException { ResultSetMetaData rsMeta = rs.getMetaData(); assertEquals("TABLE_TYPE", rsMeta.getColumnName(1)); assertEquals("", rsMeta.getTableName(1)); + assertEquals("TABLE", rs.getString(1)); + assertTrue(rs.next()); + assertEquals("SYSTEM VIEW", rs.getString(1)); + assertTrue(rs.next()); + assertEquals("VIEW", rs.getString(1)); + assertTrue(rs.next()); + assertEquals("LOCAL TEMPORARY", rs.getString(1)); + assertFalse(rs.next()); } } From 5ff1421b537b48a2646a800d34ac96dc619413e2 Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 6 Nov 2023 14:27:45 +0100 Subject: [PATCH 25/26] [CONJ-1108] Database metadata listing TEMPORARY tables/sequences - ensure null handling --- .../java/org/mariadb/jdbc/DatabaseMetaData.java | 5 ++--- .../jdbc/integration/DatabaseMetadataTest.java | 13 ++++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java index f5db93b47..5da04808f 100644 --- a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java +++ b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java @@ -738,12 +738,11 @@ public ResultSet getTables( StringBuilder sqlType = new StringBuilder(((firstCondition) ? " WHERE " : " AND ") + " TABLE_TYPE IN ("); for (String s : types) { - if (mustAddType) sqlType.append(","); - mustAddType = true; if (s == null) { - mustAddType = false; continue; } + if (mustAddType) sqlType.append(","); + mustAddType = true; switch (s) { case "TABLE": sqlType.append("'BASE TABLE','SYSTEM VERSIONED'"); diff --git a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java index f7fa25165..a7ac0f599 100644 --- a/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/DatabaseMetadataTest.java @@ -2749,7 +2749,6 @@ public void testTemporaryTables() throws SQLException { assertEquals("LOCAL TEMPORARY", rs.getString("TABLE_TYPE")); assertFalse(rs.next()); - rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"TEMPORARY"}); assertTrue(rs.next()); assertEquals("testtemporarytables",rs.getString("TABLE_NAME").toLowerCase()); @@ -2758,6 +2757,18 @@ public void testTemporaryTables() throws SQLException { rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"TABLE"}); assertFalse(rs.next()); + + rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"TEMPORARY", "TABLE"}); + assertTrue(rs.next()); + assertEquals("testtemporarytables",rs.getString("TABLE_NAME").toLowerCase()); + assertEquals("LOCAL TEMPORARY", rs.getString("TABLE_TYPE")); + assertFalse(rs.next()); + + rs = dbmd.getTables(null, null, "testTemporary%", new String[]{"TEMPORARY", null, "TABLE"}); + assertTrue(rs.next()); + assertEquals("testtemporarytables",rs.getString("TABLE_NAME").toLowerCase()); + assertEquals("LOCAL TEMPORARY", rs.getString("TABLE_TYPE")); + assertFalse(rs.next()); } } From 7ef158f93edfa89c244c01a3836cc67dbcc1d3a4 Mon Sep 17 00:00:00 2001 From: rusher Date: Mon, 6 Nov 2023 15:50:42 +0100 Subject: [PATCH 26/26] bump 3.3.0 --- CHANGELOG.md | 16 ++++++++++++++++ README.md | 4 ++-- pom.xml | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aee5f2ed9..2c58c8c3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change Log +## [3.3.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.3.0) (Nov 2023) + +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.2.0...3.3.0) + +##### Notable Changes + +* CONJ-1115 Make connector become more virtual-thread friendly +* CONJ-1108 Database metadata listing TEMPORARY tables/sequences +* CONJ-1113 update ed25519 to recent version +* CONJ-1116 Avoid unnecessary synchronization on calendar when no calendar parameter + +##### Bugs Fixed + +* CONJ-1102 BatchUpdateException.getUpdateCounts() returns SUCCESS_NO_INFO but expects EXECUTE_FAILED + + ## [3.2.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.2.0) (Aug 2023) [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.4...3.2.0) diff --git a/README.md b/README.md index fc7df60b5..90f2572be 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ or maven : org.mariadb.jdbc mariadb-java-client - 3.2.0 + 3.3.0 ``` @@ -48,7 +48,7 @@ Development snapshot are available on sonatype nexus repository org.mariadb.jdbc mariadb-java-client - 3.2.1-SNAPSHOT + 3.4.0-SNAPSHOT ``` diff --git a/pom.xml b/pom.xml index ab1d87565..88cd801bd 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ mariadb-java-client jar mariadb-java-client - 3.3.0-SNAPSHOT + 3.3.0 JDBC driver for MariaDB and MySQL https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/