Skip to content

Commit

Permalink
Merge branch 'release/1.5.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
rusher committed Oct 9, 2016
2 parents faa9628 + 15cbfab commit 7d78ca5
Show file tree
Hide file tree
Showing 16 changed files with 527 additions and 89 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ or maven :
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.5.3</version>
<version>1.5.4</version>
</dependency>
```

Expand Down
8 changes: 8 additions & 0 deletions documentation/changelog.creole
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
= Changelog
* [[https://github.com/MariaDB/mariadb-connector-j/documentation/changelog.creole#151|1.5.4]] Released on 10 Oct. 2016
* [[https://github.com/MariaDB/mariadb-connector-j/documentation/changelog.creole#151|1.5.3]] Released on 03 Oct. 2016
* [[https://github.com/MariaDB/mariadb-connector-j/documentation/changelog.creole#151|1.5.2]] Released on 31 aug. 2016
* [[https://github.com/MariaDB/mariadb-connector-j/documentation/changelog.creole#151|1.5.1]] RC released on 15 aug. 2016
Expand All @@ -12,6 +13,13 @@
* [[https://github.com/MariaDB/mariadb-connector-j/documentation/changelog.creole#140|1.4.0]] Released on 31 march 2016
---

== 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-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
Expand Down
2 changes: 1 addition & 1 deletion documentation/use-mariadb-connector-j-driver.creole
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ The following options are currently supported.
|=cacheCallableStmts| enable/disable callable Statement cache\\//Default: true. Since 1.4.0//|
|=callableStmtCacheSize| This sets the number of callable statements that the driver will cache per VM if "cacheCallableStmts" is enabled.\\//Default: true. Since 1.4.0//|
|=useBatchMultiSendNumber| When option useBatchMultiSend is active, indicate the maximum query send in a row before reading results.\\//Default: 100. Since 1.5.0//|

|=connectionAttributes| When performance_schema is active, permit to send server some client information in a key;value pair format (example: connectionAttributes=key1:value1,key2,value2).\\Those informations can be retrieved on server within tables performance_schema.session_connect_attrs and performance_schema.session_account_connect_attrs.\\This can permit from server an identification of client/application\\//Since 1.4.0//|


\\\\
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<artifactId>mariadb-java-client</artifactId>
<packaging>jar</packaging>
<name>mariadb-java-client</name>
<version>1.5.3</version>
<version>1.5.4</version>
<description>JDBC driver for MariaDB and MySQL</description>
<url>https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/</url>

Expand Down
114 changes: 109 additions & 5 deletions src/main/java/org/mariadb/jdbc/MariaDbConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.mariadb.jdbc.internal.util.dao.CallableStatementCacheKey;
import org.mariadb.jdbc.internal.util.dao.CloneableCallableStatement;
import org.mariadb.jdbc.internal.util.dao.QueryException;
import org.mariadb.jdbc.internal.util.dao.ServerPrepareResult;

import java.net.SocketException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -1096,7 +1096,72 @@ public boolean isValid(final int timeout) throws SQLException {
* @since 1.6
*/
public void setClientInfo(final String name, final String value) throws SQLClientInfoException {
DefaultOptions.addProperty(protocol.getUrlParser().getHaMode(), name, value, this.options);
if (protocol.isExplicitClosed()) {
Map<String, ClientInfoStatus> failures = new HashMap<>();
failures.put(name, ClientInfoStatus.REASON_UNKNOWN);
throw new SQLClientInfoException("setClientInfo() is called on closed connection", failures);
}

if (protocol.isClosed() && protocol.getProxy() != null) {
lock.lock();
try {
protocol.getProxy().reconnect();
} catch (SQLException sqle) {
Map<String, ClientInfoStatus> failures = new HashMap<>();
failures.put(name, ClientInfoStatus.REASON_UNKNOWN);
throw new SQLClientInfoException("Connection closed", failures, sqle);
} finally {
lock.unlock();
}
}

if (name == null || (!"ApplicationName".equals(name)
&& !"ClientUser".equals(name)
&& !"ClientHostname".equals(name))) {
Map<String, ClientInfoStatus> failures = new HashMap<>();
failures.put(name, ClientInfoStatus.REASON_UNKNOWN_PROPERTY);
throw new SQLClientInfoException("setClientInfo() parameters can only be \"ApplicationName\",\"ClientUser\" or \"ClientHostname\", "
+ "but was : " + name, failures);
}

StringBuilder escapeQuery = new StringBuilder("SET @").append(name).append("=");
if (value == null) {
escapeQuery.append("null");
} else {
escapeQuery.append("'");
int charsOffset = 0;
int charsLength = value.length();
char charValue;
if (noBackslashEscapes) {
do {
charValue = value.charAt(charsOffset);
if (charValue == '\'') escapeQuery.append('\''); //add a single escape quote
escapeQuery.append(charValue);
charsOffset++;
} while (charsOffset < charsLength);
} else {
do {
charValue = value.charAt(charsOffset);
if (charValue == '\''
|| charValue == '\\'
|| charValue == '"'
|| charValue == 0) escapeQuery.append('\\'); //add escape slash
escapeQuery.append(charValue);
charsOffset++;
} while (charsOffset < charsLength);
}
escapeQuery.append("'");
}

try {
Statement statement = createStatement();
statement.execute(escapeQuery.toString());
} catch (SQLException sqle) {
Map<String, ClientInfoStatus> failures = new HashMap<>();
failures.put(name, ClientInfoStatus.REASON_UNKNOWN);
throw new SQLClientInfoException("unexpected error during setClientInfo", failures, sqle);

}
}

/**
Expand All @@ -1117,7 +1182,19 @@ public void setClientInfo(final String name, final String value) throws SQLClien
* @since 1.6
*/
public void setClientInfo(final Properties properties) throws SQLClientInfoException {
DefaultOptions.addProperty(protocol.getUrlParser().getHaMode(), properties, this.options);
Map<String, ClientInfoStatus> propertiesExceptions = new HashMap<>();
for (String name : new String[]{"ApplicationName", "ClientUser", "ClientHostname"}) {
try {
setClientInfo(name, properties.getProperty(name));
} catch (SQLClientInfoException e) {
propertiesExceptions.putAll(e.getFailedProperties());
}
}

if (!propertiesExceptions.isEmpty()) {
String errorMsg = "setClientInfo errors : the following properties where not set : " + propertiesExceptions.keySet();
throw new SQLClientInfoException(errorMsg, propertiesExceptions);
}
}

/**
Expand All @@ -1135,7 +1212,18 @@ public void setClientInfo(final Properties properties) throws SQLClientInfoExcep
* @since 1.6
*/
public String getClientInfo(final String name) throws SQLException {
return DefaultOptions.getProperties(name, options);
checkConnection();
if (!"ApplicationName".equals(name) && !"ClientUser".equals(name) && !"ClientHostname".equals(name)) {
throw new SQLException("name must be \"ApplicationName\", \"ClientUser\" or \"ClientHostname\", but was \"" + name + "\"");
}
try (Statement statement = createStatement()) {
try (ResultSet rs = statement.executeQuery("SELECT @" + name)) {
if (rs.next()) {
return rs.getString(1);
}
}
}
return null;
}

/**
Expand All @@ -1149,7 +1237,23 @@ public String getClientInfo(final String name) throws SQLException {
* @since 1.6
*/
public Properties getClientInfo() throws SQLException {
return DefaultOptions.getProperties(options);
checkConnection();
try (Statement statement = createStatement()) {
try (ResultSet rs = statement.executeQuery("SELECT @ApplicationName, @ClientUser, @ClientHostname")) {
if (rs.next()) {
Properties properties = new Properties();
if (rs.getString(1) != null) properties.setProperty("ApplicationName", rs.getString(1));
if (rs.getString(2) != null) properties.setProperty("ClientUser", rs.getString(2));
if (rs.getString(3) != null) properties.setProperty("ClientHostname", rs.getString(3));
return properties;
}
}
}
Properties properties = new Properties();
properties.setProperty("ApplicationName", null);
properties.setProperty("ClientUser", null);
properties.setProperty("ClientHostname", null);
return new Properties();
}


Expand Down
48 changes: 45 additions & 3 deletions src/main/java/org/mariadb/jdbc/MariaDbDatabaseMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS

package org.mariadb.jdbc;

import org.mariadb.jdbc.internal.packet.dao.ColumnInformation;
import org.mariadb.jdbc.internal.queryresults.resultset.MariaSelectResultSet;
import org.mariadb.jdbc.internal.util.Utils;
import org.mariadb.jdbc.internal.util.constant.Version;
Expand Down Expand Up @@ -631,7 +632,8 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa
+ " 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 = 'auto_increment','YES','NO') IS_AUTOINCREMENT, "
+ " IF(EXTRA in ('VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO') IS_GENERATEDCOLUMN "
+ " FROM INFORMATION_SCHEMA.COLUMNS WHERE "
+ catalogCond("TABLE_SCHEMA", catalog)
+ " AND "
Expand Down Expand Up @@ -2346,9 +2348,49 @@ public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
return false;
}

/**
* Retrieves a list of the client info properties that the driver supports. The result set contains the following columns
* <ol>
* <li>NAME String : The name of the client info property</li>
* <li>MAX_LEN int : The maximum length of the value for the property</li>
* <li>DEFAULT_VALUE String : The default value of the property</li>
* <li>DESCRIPTION String : A description of the property.
* This will typically contain information as to where this property is stored in the database.</li>
* </ol>
* The ResultSet is sorted by the NAME column
* @return A ResultSet object; each row is a supported client info property
* @throws SQLException if connection error occur
*/
public ResultSet getClientInfoProperties() throws SQLException {
String sql = "SELECT ' ' NAME, 0 MAX_LEN, ' ' DEFAULT_VALUE, ' ' DESCRIPTION FROM DUAL WHERE 1=0";
return executeQuery(sql);
ColumnInformation[] columns = new ColumnInformation[4];
columns[0] = ColumnInformation.create("NAME", MariaDbType.STRING);
columns[1] = ColumnInformation.create("MAX_LEN", MariaDbType.INTEGER);
columns[2] = ColumnInformation.create("DEFAULT_VALUE", MariaDbType.STRING);
columns[3] = ColumnInformation.create("DESCRIPTION", MariaDbType.STRING);


List<byte[][]> rows = new ArrayList<>(3);
rows.add(new byte[][] {
"ApplicationName".getBytes(),
new byte[] {(byte) 49, (byte) 54, (byte) 55, (byte) 55, (byte) 55, (byte) 50, (byte) 49, (byte) 53}, //16Mb
new byte[]{},
"The name of the application currently utilizing the connection".getBytes()
});
rows.add(new byte[][] {
"ClientUser".getBytes(),
new byte[] {(byte) 49, (byte) 54, (byte) 55, (byte) 55, (byte) 55, (byte) 50, (byte) 49, (byte) 53}, //16Mb
new byte[]{},
("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.").getBytes()
});
rows.add(new byte[][] {
"ClientHostname".getBytes(),
new byte[] {(byte) 49, (byte) 54, (byte) 55, (byte) 55, (byte) 55, (byte) 50, (byte) 49, (byte) 53}, //16Mb
new byte[]{},
"The hostname of the computer the application using the connection is running on".getBytes()
});

return new MariaSelectResultSet(columns, rows, connection.getProtocol(), ResultSet.TYPE_SCROLL_INSENSITIVE);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ private void escapeUtf8() {
charsOffset = 0;
position = 0;

//handle "" String value
if (charsLength == 0) {
position = 2;
escapedArray = new byte[] {(byte)'\'', (byte)'\''};
return;
}

//create UTF-8 byte array
//since java char are internally using UTF-16 using surrogate's pattern, 4 bytes unicode characters will
//represent 2 characters : example "\uD83C\uDFA4" = 🎤 unicode 8 "no microphones"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
import org.mariadb.jdbc.MariaDbDatabaseMetaData;
import org.mariadb.jdbc.internal.MariaDbServerCapabilities;
import org.mariadb.jdbc.internal.protocol.authentication.DefaultAuthenticationProvider;
import org.mariadb.jdbc.internal.util.PidFactory;
import org.mariadb.jdbc.internal.util.Utils;
import org.mariadb.jdbc.internal.stream.PacketOutputStream;
import org.mariadb.jdbc.internal.util.constant.Version;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.StringTokenizer;
Expand Down Expand Up @@ -205,12 +205,11 @@ private void writeConnectAttributes(PacketOutputStream writeBuffer) {
writeStringLength("_client_name", MariaDbDatabaseMetaData.DRIVER_NAME);
writeStringLength("_client_version", Version.version);
writeStringLength("_os", System.getProperty("os.name"));
try {
writeStringLength("_pid", ManagementFactory.getRuntimeMXBean().getName());
} catch (NoClassDefFoundError e) {
/* [CONJ-281] GAE support */
}
writeStringLength("_thread", Long.toString(serverThreadId));

String pid = PidFactory.getInstance().getPid();
if (pid != null) writeStringLength("_pid", pid);

writeStringLength("_thread", Long.toString(Thread.currentThread().getId()));
writeStringLength("_java_vendor", System.getProperty("java.vendor"));
writeStringLength("_java_version", System.getProperty("java.version"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ private void initializeSocketOption() {
socket.setSoLinger(true, 0);
}
} catch (Exception e) {
// if (log.isDebugEnabled())log.debug("Failed to set socket option: " + e.getLocalizedMessage());
logger.debug("Failed to set socket option", e);
}
}

Expand Down
Loading

0 comments on commit 7d78ca5

Please sign in to comment.