From fb57f5035c68b88da20d7b8436629f122ab2ecb4 Mon Sep 17 00:00:00 2001 From: diego Dupin Date: Wed, 20 Jul 2022 14:32:01 +0200 Subject: [PATCH] [CONJ-986] adding Statement.setLocalInfileInputStream() for 2.x compatibility --- .../mariadb/jdbc/ClientPreparedStatement.java | 9 +- .../java/org/mariadb/jdbc/Configuration.java | 2 +- .../mariadb/jdbc/ServerPreparedStatement.java | 17 ++- src/main/java/org/mariadb/jdbc/Statement.java | 15 ++- .../mariadb/jdbc/message/ClientMessage.java | 53 ++++++--- .../jdbc/message/client/ExecutePacket.java | 13 ++- .../jdbc/message/client/QueryPacket.java | 12 ++ .../client/QueryWithParametersPacket.java | 13 ++- .../jdbc/integration/LocalInfileTest.java | 110 ++++++++++++++++++ .../jdbc/unit/util/ConfigurationTest.java | 2 +- 10 files changed, 214 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java b/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java index 64dcf039c..2d4927e48 100644 --- a/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java @@ -89,7 +89,7 @@ private void executeInternal() throws SQLException { lock.lock(); try { QueryWithParametersPacket query = - new QueryWithParametersPacket(preSqlCmd(), parser, parameters); + new QueryWithParametersPacket(preSqlCmd(), parser, parameters, localInfileInputStream); results = con.getClient() .execute( @@ -102,6 +102,7 @@ private void executeInternal() throws SQLException { closeOnCompletion, false); } finally { + localInfileInputStream = null; lock.unlock(); } } @@ -187,7 +188,7 @@ private void executeBatchBulk() throws SQLException { private void executeBatchPipeline() throws SQLException { ClientMessage[] packets = new ClientMessage[batchParameters.size()]; for (int i = 0; i < batchParameters.size(); i++) { - packets[i] = new QueryWithParametersPacket(preSqlCmd(), parser, batchParameters.get(i)); + packets[i] = new QueryWithParametersPacket(preSqlCmd(), parser, batchParameters.get(i), null); } try { results = @@ -220,7 +221,8 @@ private void executeBatchStd() throws SQLException { results.addAll( con.getClient() .execute( - new QueryWithParametersPacket(preSqlCmd(), parser, batchParameters.get(i)), + new QueryWithParametersPacket( + preSqlCmd(), parser, batchParameters.get(i), localInfileInputStream), this, 0, maxRows, @@ -233,6 +235,7 @@ private void executeBatchStd() throws SQLException { BatchUpdateException exception = exceptionFactory().createBatchUpdate(results, batchParameters.size(), bue); results = null; + localInfileInputStream = null; throw exception; } } diff --git a/src/main/java/org/mariadb/jdbc/Configuration.java b/src/main/java/org/mariadb/jdbc/Configuration.java index a9263fe9c..5bc9ab12d 100644 --- a/src/main/java/org/mariadb/jdbc/Configuration.java +++ b/src/main/java/org/mariadb/jdbc/Configuration.java @@ -97,7 +97,7 @@ public class Configuration { // protocol private boolean allowMultiQueries = false; - private boolean allowLocalInfile = false; + private boolean allowLocalInfile = true; private boolean useCompression = false; private boolean useAffectedRows = false; private boolean useBulkStmts = true; diff --git a/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java b/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java index af214225d..5f2cda37c 100644 --- a/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java @@ -98,6 +98,7 @@ protected void executeInternal() throws SQLException { executeStandard(cmd); } } finally { + localInfileInputStream = null; lock.unlock(); } } @@ -112,7 +113,7 @@ private void executePipeline(String cmd) throws SQLException { // server is 10.2+, permitting to execute last prepare with (-1) statement id. // Server send prepare, followed by execute, in one exchange. PreparePacket prepare = new PreparePacket(cmd); - ExecutePacket execute = new ExecutePacket(null, parameters, cmd, this); + ExecutePacket execute = new ExecutePacket(null, parameters, cmd, this, localInfileInputStream); try { List res = con.getClient() @@ -142,7 +143,8 @@ private void executeStandard(String cmd) throws SQLException { } validParameters(); // send COM_STMT_EXECUTE - ExecutePacket execute = new ExecutePacket(prepareResult, parameters, cmd, this); + ExecutePacket execute = + new ExecutePacket(prepareResult, parameters, cmd, this, localInfileInputStream); results = con.getClient() .execute( @@ -273,7 +275,9 @@ private List executeBunch(String cmd, int index, int maxCmd) throws int maxCmdToSend = Math.min(batchParameters.size() - index, maxCmd); ClientMessage[] packets = new ClientMessage[maxCmdToSend]; for (int i = index; i < index + maxCmdToSend; i++) { - packets[i - index] = new ExecutePacket(prepareResult, batchParameters.get(i), cmd, this); + packets[i - index] = + new ExecutePacket( + prepareResult, batchParameters.get(i), cmd, this, localInfileInputStream); } return con.getClient() .executePipeline( @@ -293,7 +297,8 @@ private List executeBunchPrepare(String cmd, int index, int maxCmd) ClientMessage[] packets = new ClientMessage[maxCmdToSend + 1]; packets[0] = new PreparePacket(cmd); for (int i = index; i < index + maxCmdToSend; i++) { - packets[i + 1 - index] = new ExecutePacket(null, batchParameters.get(i), cmd, this); + packets[i + 1 - index] = + new ExecutePacket(null, batchParameters.get(i), cmd, this, localInfileInputStream); } List res = con.getClient() @@ -334,7 +339,8 @@ private void executeBatchStandard(String cmd) throws SQLException { } } try { - ExecutePacket execute = new ExecutePacket(prepareResult, batchParameter, cmd, this); + ExecutePacket execute = + new ExecutePacket(prepareResult, batchParameter, cmd, this, localInfileInputStream); tmpResults.addAll(con.getClient().execute(execute, this, false)); } catch (SQLException e) { if (error == null) error = e; @@ -619,6 +625,7 @@ public int[] executeBatch() throws SQLException { return updates; } finally { + localInfileInputStream = null; batchParameters.clear(); lock.unlock(); } diff --git a/src/main/java/org/mariadb/jdbc/Statement.java b/src/main/java/org/mariadb/jdbc/Statement.java index be96ba42e..b43b65dc8 100644 --- a/src/main/java/org/mariadb/jdbc/Statement.java +++ b/src/main/java/org/mariadb/jdbc/Statement.java @@ -6,6 +6,7 @@ import static org.mariadb.jdbc.util.constants.Capabilities.LOCAL_FILES; +import java.io.InputStream; import java.sql.*; import java.util.ArrayList; import java.util.List; @@ -57,6 +58,8 @@ public class Statement implements java.sql.Statement { protected List results; /** current results */ protected Completion currResult; + /** streaming load data infile data */ + protected InputStream localInfileInputStream; /** * Constructor @@ -93,6 +96,11 @@ private ExceptionFactory exceptionFactory() { return con.getExceptionFactory().of(this); } + public void setLocalInfileInputStream(InputStream inputStream) throws SQLException { + checkNotClosed(); + localInfileInputStream = inputStream; + } + /** * Executes the given SQL statement, which returns a single ResultSet object. * @@ -919,7 +927,7 @@ private void executeInternal(String sql, int autoGeneratedKeys) throws SQLExcept results = con.getClient() .execute( - new QueryPacket(cmd), + new QueryPacket(cmd, localInfileInputStream), this, fetchSize, maxRows, @@ -928,6 +936,7 @@ private void executeInternal(String sql, int autoGeneratedKeys) throws SQLExcept closeOnCompletion, false); } finally { + localInfileInputStream = null; lock.unlock(); } } @@ -1513,7 +1522,7 @@ public List executeInternalBatchStandard() throws SQLException { results.addAll( con.getClient() .execute( - new QueryPacket(batchQuery), + new QueryPacket(batchQuery, localInfileInputStream), this, 0, 0L, @@ -1531,6 +1540,8 @@ public List executeInternalBatchStandard() throws SQLException { completion instanceof OkPacket ? (int) ((OkPacket) completion).getAffectedRows() : 0; } throw new BatchUpdateException(sqle.getMessage(), updateCounts, sqle); + } finally { + localInfileInputStream = null; } } } diff --git a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java index d2b97cc99..bc752fc36 100644 --- a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java @@ -138,31 +138,44 @@ default Completion readPacket( errorPacket.getMessage(), errorPacket.getSqlState(), errorPacket.getErrorCode()); case 0xfb: buf.skip(1); // skip header - String fileName = buf.readStringNullEnd(); - SQLException exception = null; - if (!message.validateLocalFileName(fileName, context)) { - exception = - exceptionFactory - .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", - fileName, this.description()), - "HY000"); - } else { - try (InputStream is = new FileInputStream(fileName)) { + + InputStream is = getLocalInfileInputStream(); + if (is == null) { + String fileName = buf.readStringNullEnd(); + if (!message.validateLocalFileName(fileName, context)) { + exception = + exceptionFactory + .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", + fileName, this.description()), + "HY000"); + } else { + + try { + is = new FileInputStream(fileName); + } catch (FileNotFoundException f) { + exception = + exceptionFactory + .withSql(this.description()) + .create("Could not send file : " + f.getMessage(), "HY000", f); + } + } + } + + // sending stream + if (is != null) { + try { byte[] fileBuf = new byte[8192]; int len; while ((len = is.read(fileBuf)) > 0) { writer.writeBytes(fileBuf, 0, len); writer.flush(); } - } catch (FileNotFoundException f) { - exception = - exceptionFactory - .withSql(this.description()) - .create("Could not send file : " + f.getMessage(), "HY000", f); + } finally { + is.close(); } } @@ -261,6 +274,10 @@ default Completion readPacket( } } + default InputStream getLocalInfileInputStream() { + return null; + } + /** * Request for local file to be validated from current query. * 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 bde264155..203e925bb 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java @@ -5,6 +5,7 @@ package org.mariadb.jdbc.message.client; import java.io.IOException; +import java.io.InputStream; import java.sql.SQLException; import org.mariadb.jdbc.ServerPreparedStatement; import org.mariadb.jdbc.client.Context; @@ -25,6 +26,7 @@ public final class ExecutePacket implements RedoableWithPrepareClientMessage { private final String command; private final ServerPreparedStatement prep; private Prepare prepareResult; + private InputStream localInfileInputStream; /** * Constructor @@ -35,11 +37,16 @@ public final class ExecutePacket implements RedoableWithPrepareClientMessage { * @param prep prepared statement */ public ExecutePacket( - Prepare prepareResult, Parameters parameters, String command, ServerPreparedStatement prep) { + Prepare prepareResult, + Parameters parameters, + String command, + ServerPreparedStatement prep, + InputStream localInfileInputStream) { this.parameters = parameters; this.prepareResult = prepareResult; this.command = command; this.prep = prep; + this.localInfileInputStream = localInfileInputStream; } public void saveParameters() { @@ -131,6 +138,10 @@ public String getCommand() { return command; } + public InputStream getLocalInfileInputStream() { + return localInfileInputStream; + } + public ServerPreparedStatement prep() { return prep; } diff --git a/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java b/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java index a24310376..3f5745462 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java @@ -5,6 +5,7 @@ package org.mariadb.jdbc.message.client; import java.io.IOException; +import java.io.InputStream; import org.mariadb.jdbc.client.Context; import org.mariadb.jdbc.client.socket.Writer; import org.mariadb.jdbc.message.ClientMessage; @@ -13,6 +14,7 @@ public final class QueryPacket implements RedoableClientMessage { private final String sql; + private final InputStream localInfileInputStream; /** * Constructor @@ -21,6 +23,12 @@ public final class QueryPacket implements RedoableClientMessage { */ public QueryPacket(String sql) { this.sql = sql; + this.localInfileInputStream = null; + } + + public QueryPacket(String sql, InputStream localInfileInputStream) { + this.sql = sql; + this.localInfileInputStream = localInfileInputStream; } public int batchUpdateLength() { @@ -49,6 +57,10 @@ public boolean validateLocalFileName(String fileName, Context context) { return ClientMessage.validateLocalFileName(sql, null, fileName, context); } + public InputStream getLocalInfileInputStream() { + return localInfileInputStream; + } + public String description() { return sql; } diff --git a/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java b/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java index 88203596f..bbef798e7 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java @@ -5,6 +5,7 @@ package org.mariadb.jdbc.message.client; import java.io.IOException; +import java.io.InputStream; import java.sql.SQLException; import org.mariadb.jdbc.client.Context; import org.mariadb.jdbc.client.socket.Writer; @@ -23,6 +24,7 @@ public final class QueryWithParametersPacket implements RedoableClientMessage { private final String preSqlCmd; private final ClientParser parser; private Parameters parameters; + private InputStream localInfileInputStream; /** * Constructor @@ -31,10 +33,15 @@ public final class QueryWithParametersPacket implements RedoableClientMessage { * @param parser command parser result * @param parameters parameters */ - public QueryWithParametersPacket(String preSqlCmd, ClientParser parser, Parameters parameters) { + public QueryWithParametersPacket( + String preSqlCmd, + ClientParser parser, + Parameters parameters, + InputStream localInfileInputStream) { this.preSqlCmd = preSqlCmd; this.parser = parser; this.parameters = parameters; + this.localInfileInputStream = localInfileInputStream; } @Override @@ -83,6 +90,10 @@ public boolean validateLocalFileName(String fileName, Context context) { return ClientMessage.validateLocalFileName(parser.getSql(), parameters, fileName, context); } + public InputStream getLocalInfileInputStream() { + return localInfileInputStream; + } + @Override public String description() { return parser.getSql(); diff --git a/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java b/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java index c71d524f8..14e315fab 100644 --- a/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java +++ b/src/test/java/org/mariadb/jdbc/integration/LocalInfileTest.java @@ -22,6 +22,8 @@ public static void beforeAll2() throws SQLException { 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"); + stmt.execute( + "CREATE TABLE big_load_data_infile(id int not null primary key auto_increment, name char(20)) ENGINE=myisam"); stmt.execute("FLUSH TABLES"); } @@ -34,6 +36,7 @@ public static void drop() throws SQLException { stmt.execute("DROP TABLE IF EXISTS ttlocal"); stmt.execute("DROP TABLE IF EXISTS ldinfile"); stmt.execute("DROP TABLE IF EXISTS `infile`"); + stmt.execute("DROP TABLE IF EXISTS big_load_data_infile"); } private static boolean checkLocal() throws SQLException { @@ -45,6 +48,113 @@ private static boolean checkLocal() throws SQLException { return false; } + @Test + public void bigLoadDataInfileTest() throws SQLException, IOException { + Assumptions.assumeTrue(runLongTest()); + try (VeryLongAutoGeneratedInputStream in = new VeryLongAutoGeneratedInputStream(5000000)) { + try (Connection connection = createCon("&allowLocalInfile=true")) { + Statement statement = connection.createStatement(); + org.mariadb.jdbc.Statement mariaDbStatement = + statement.unwrap(org.mariadb.jdbc.Statement.class); + mariaDbStatement.setLocalInfileInputStream(in); + + String sql = + "LOAD DATA LOCAL INFILE 'dummyFileName'" + + " INTO TABLE big_load_data_infile " + + " FIELDS TERMINATED BY '\\t' ENCLOSED BY ''" + + " ESCAPED BY '\\\\' LINES TERMINATED BY '\\n'"; + + assertFalse(statement.execute(sql)); + ResultSet rs = statement.executeQuery("select count(*) from big_load_data_infile"); + assertTrue(rs.next()); + assertEquals(in.numberOfRows, rs.getInt(1)); + } + } + } + + /** Custom memory conserving generator of a LOAD DATA INFILE that generates a stream. */ + private static class VeryLongAutoGeneratedInputStream extends InputStream { + + private final int numberOfRows; + private int currentPosInBuffer; + private byte[] buffer; + private int currentRow; + + private VeryLongAutoGeneratedInputStream(int numberOfRows) { + this.numberOfRows = numberOfRows; + currentRow = 0; + } + + @Override + public int read() { + if (currentRow > numberOfRows) { + return -1; + } + if (buffer != null && currentPosInBuffer >= buffer.length) { + buffer = null; + } + if (buffer == null) { + currentRow++; + currentPosInBuffer = 0; + buffer = (currentRow + "\tname" + currentRow + "\n").getBytes(); + } + return buffer[currentPosInBuffer++]; + } + } + + @Test + public void streamInBatch() throws SQLException, IOException { + Assumptions.assumeFalse((!isMariaDBServer() && minVersion(8, 0, 3))); + Assumptions.assumeTrue( + !"skysql".equals(System.getenv("srv")) && !"skysql-ha".equals(System.getenv("srv"))); + String batch_update = + "LOAD DATA LOCAL INFILE 'dummy.tsv' INTO TABLE LocalInfileInputStreamTest2 (id, test)"; + String builder = "1\thello\n2\tworld\n"; + + Statement stmt = sharedConn.createStatement(); + stmt.execute("TRUNCATE LocalInfileInputStreamTest2"); + InputStream inputStream = new ByteArrayInputStream(builder.getBytes()); + ((org.mariadb.jdbc.Statement) stmt).setLocalInfileInputStream(inputStream); + stmt.addBatch(batch_update); + stmt.addBatch("SET UNIQUE_CHECKS=1"); + stmt.executeBatch(); + stmt.addBatch(batch_update); + try { + stmt.executeBatch(); + } catch (SQLException e) { + assertTrue(e.getCause().getCause() instanceof FileNotFoundException); + } + + try (PreparedStatement prep = + sharedConn.prepareStatement( + "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(); + prep.executeBatch(); + try { + prep.addBatch(); + prep.executeBatch(); + } catch (SQLException e) { + assertTrue(e.getCause().getCause() instanceof FileNotFoundException); + } + } + try (PreparedStatement prep = + sharedConnBinary.prepareStatement( + "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(); + prep.executeBatch(); + try { + prep.addBatch(); + prep.executeBatch(); + } catch (SQLException e) { + assertTrue(e.getCause().getCause() instanceof FileNotFoundException); + } + } + } + @Test public void throwExceptions() throws Exception { Assumptions.assumeTrue( 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 0c1145a03..4cad1c88d 100644 --- a/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java +++ b/src/test/java/org/mariadb/jdbc/unit/util/ConfigurationTest.java @@ -829,7 +829,7 @@ public void builder() throws SQLException { .initSql("SET @@a='10'") .build(); assertEquals( - "jdbc:mariadb://host1:3305,address=(host=host2)(port=3307)(type=replica)/db?user=me&password=***&timezone=UTC&autocommit=false&createDatabaseIfNotExist=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&tcpKeepAlive=false&tcpKeepIdle=10&tcpKeepCount=50&tcpKeepInterval=50&tcpAbortiveClose=true&localSocketAddress=localSocketAddress&socketTimeout=1000&useReadAheadInput=false&tlsSocketType=TLStype&sslMode=TRUST&serverSslCert=mycertPath&keyStore=/tmp&keyStorePassword=MyPWD&keyStoreType=JKS&enabledSslCipherSuites=myCipher,cipher2&enabledSslProtocolSuites=TLSv1.2&allowMultiQueries=true&useCompression=true&useAffectedRows=true&useBulkStmts=false&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&createDatabaseIfNotExist=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&tcpKeepAlive=false&tcpKeepIdle=10&tcpKeepCount=50&tcpKeepInterval=50&tcpAbortiveClose=true&localSocketAddress=localSocketAddress&socketTimeout=1000&useReadAheadInput=false&tlsSocketType=TLStype&sslMode=TRUST&serverSslCert=mycertPath&keyStore=/tmp&keyStorePassword=MyPWD&keyStoreType=JKS&enabledSslCipherSuites=myCipher,cipher2&enabledSslProtocolSuites=TLSv1.2&allowMultiQueries=true&allowLocalInfile=false&useCompression=true&useAffectedRows=true&useBulkStmts=false&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()); }