Skip to content

Commit

Permalink
Fix for Bug#88227 (27029657), Connector/J 5.1.44 cannot be used again…
Browse files Browse the repository at this point in the history
…st MySQL 5.7.20 without warnings.
  • Loading branch information
fjssilva committed Jan 31, 2018
1 parent b79d648 commit 2c80333
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 49 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 5.1.46

- Fix for Bug#88227 (27029657), Connector/J 5.1.44 cannot be used against MySQL 5.7.20 without warnings.

- Fix for Bug#27374581, CONNECTION FAILS WHEN GPL SERVER STARTED WITH TLS-VERSION=TLSV1.2.

- Fix for Bug#79612 (22362474), CONNECTION ATTRIBUTES LOST WHEN CONNECTING WITHOUT DEFAULT DATABASE.
Expand Down
57 changes: 20 additions & 37 deletions src/com/mysql/jdbc/ConnectionImpl.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -1277,8 +1277,10 @@ private void checkServerEncoding() throws SQLException {
* @throws SQLException
*/
private void checkTransactionIsolationLevel() throws SQLException {
String txIsolationName = versionMeetsMinimum(4, 0, 3) && !versionMeetsMinimum(8, 0, 3) ? "tx_isolation" : "transaction_isolation";
String s = this.serverVariables.get(txIsolationName);
String s = this.serverVariables.get("transaction_isolation");
if (s == null) {
s = this.serverVariables.get("tx_isolation");
}

if (s != null) {
Integer intTI = mapTransIsolationNameToValue.get(s);
Expand Down Expand Up @@ -2992,30 +2994,19 @@ public int getTransactionIsolation() throws SQLException {

try {
stmt = getMetadataSafeStatement();

String query = null;

int offset = 1;

if (versionMeetsMinimum(8, 0, 3)) {
query = "SELECT @@session.transaction_isolation";
} else if (versionMeetsMinimum(4, 0, 3)) {
query = "SELECT @@session.tx_isolation";
} else {
query = "SHOW VARIABLES LIKE 'transaction_isolation'";
offset = 2;
}

String query = versionMeetsMinimum(8, 0, 3) || (versionMeetsMinimum(5, 7, 20) && !versionMeetsMinimum(8, 0, 0))
? "SELECT @@session.transaction_isolation" : "SELECT @@session.tx_isolation";
rs = stmt.executeQuery(query);

if (rs.next()) {
String s = rs.getString(offset);
String s = rs.getString(1);

if (s != null) {
Integer intTI = mapTransIsolationNameToValue.get(s);

if (intTI != null) {
return intTI.intValue();
this.isolationLevel = intTI.intValue();
return this.isolationLevel;
}
}

Expand Down Expand Up @@ -3543,7 +3534,8 @@ public boolean isReadOnly(boolean useSessionStatus) throws SQLException {
try {
stmt = getMetadataSafeStatement();

rs = stmt.executeQuery(versionMeetsMinimum(8, 0, 3) ? "select @@session.transaction_read_only" : "select @@session.tx_read_only");
rs = stmt.executeQuery(versionMeetsMinimum(8, 0, 3) || (versionMeetsMinimum(5, 7, 20) && !versionMeetsMinimum(8, 0, 0))
? "select @@session.transaction_read_only" : "select @@session.tx_read_only");
if (rs.next()) {
return rs.getInt(1) != 0; // mysql has a habit of tri+ state booleans
}
Expand Down Expand Up @@ -3753,6 +3745,9 @@ private void loadServerVariables() throws SQLException {

this.serverVariables = new HashMap<String, String>();

boolean currentJdbcComplTrunc = this.getJdbcCompliantTruncation();
setJdbcCompliantTruncation(false); // Temporarily disabling data truncation check avoids unnecessary SHOW WARNINGS on deprecated vars.

try {
if (versionMeetsMinimum(5, 1, 0)) {
StringBuilder queryBuf = new StringBuilder(versionComment).append("SELECT");
Expand All @@ -3772,19 +3767,17 @@ private void loadServerVariables() throws SQLException {
queryBuf.append(", @@max_allowed_packet AS max_allowed_packet");
queryBuf.append(", @@net_buffer_length AS net_buffer_length");
queryBuf.append(", @@net_write_timeout AS net_write_timeout");
if (versionMeetsMinimum(8, 0, 3)) {
queryBuf.append(", @@have_query_cache AS have_query_cache");
} else {
if (!versionMeetsMinimum(8, 0, 3)) {
queryBuf.append(", @@query_cache_size AS query_cache_size");
queryBuf.append(", @@query_cache_type AS query_cache_type");
}
queryBuf.append(", @@sql_mode AS sql_mode");
queryBuf.append(", @@system_time_zone AS system_time_zone");
queryBuf.append(", @@time_zone AS time_zone");
if (versionMeetsMinimum(8, 0, 3)) {
if (versionMeetsMinimum(8, 0, 3) || (versionMeetsMinimum(5, 7, 20) && !versionMeetsMinimum(8, 0, 0))) {
queryBuf.append(", @@transaction_isolation AS transaction_isolation");
} else {
queryBuf.append(", @@tx_isolation AS tx_isolation");
queryBuf.append(", @@tx_isolation AS transaction_isolation");
}
queryBuf.append(", @@wait_timeout AS wait_timeout");

Expand All @@ -3795,18 +3788,6 @@ private void loadServerVariables() throws SQLException {
this.serverVariables.put(rsmd.getColumnLabel(i), results.getString(i));
}
}

if (versionMeetsMinimum(8, 0, 3) && "YES".equalsIgnoreCase(this.serverVariables.get("have_query_cache"))) {
results.close();
results = stmt.executeQuery("SELECT @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type");
if (results.next()) {
ResultSetMetaData rsmd = results.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
this.serverVariables.put(rsmd.getColumnLabel(i), results.getString(i));
}
}
}

} else {
results = stmt.executeQuery(versionComment + "SHOW VARIABLES");
while (results.next()) {
Expand All @@ -3820,6 +3801,8 @@ private void loadServerVariables() throws SQLException {
if (ex.getErrorCode() != MysqlErrorNumbers.ER_MUST_CHANGE_PASSWORD || getDisconnectOnExpiredPasswords()) {
throw ex;
}
} finally {
setJdbcCompliantTruncation(currentJdbcComplTrunc);
}

if (getCacheServerConfiguration()) {
Expand Down
4 changes: 3 additions & 1 deletion src/com/mysql/jdbc/MysqlIO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -4181,7 +4181,9 @@ boolean hadWarnings() {

void scanForAndThrowDataTruncation() throws SQLException {
if ((this.streamingData == null) && versionMeetsMinimum(4, 1, 0) && this.connection.getJdbcCompliantTruncation() && this.warningCount > 0) {
int warningCountOld = this.warningCount;
SQLError.convertShowWarningsToSQLWarnings(this.connection, this.warningCount, true);
this.warningCount = warningCountOld;
}
}

Expand Down
57 changes: 48 additions & 9 deletions src/testsuite/regression/ConnectionRegressionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
import com.mysql.jdbc.SQLError;
import com.mysql.jdbc.SocketMetadata;
import com.mysql.jdbc.StandardSocketFactory;
import com.mysql.jdbc.StatementInterceptorV2;
import com.mysql.jdbc.StringUtils;
import com.mysql.jdbc.TimeUtil;
import com.mysql.jdbc.Util;
Expand Down Expand Up @@ -7569,6 +7570,11 @@ public void testBug75592() throws Exception {
serverVariables.put(this.rs.getString(1), this.rs.getString(2));
}

// fix the renaming of "tx_isolation" to "transaction_isolation" that is made in Connection.loadServerVariables().
if (con.versionMeetsMinimum(5, 1, 0) && !serverVariables.containsKey("transaction_isolation") && serverVariables.containsKey("tx_isolation")) {
serverVariables.put("transaction_isolation", serverVariables.remove("tx_isolation"));
}

// check values from "select @@var..."
assertEquals(serverVariables.get("auto_increment_increment"), con.getServerVariable("auto_increment_increment"));
assertEquals(serverVariables.get("character_set_client"), con.getServerVariable("character_set_client"));
Expand All @@ -7589,10 +7595,7 @@ public void testBug75592() throws Exception {
assertEquals(serverVariables.get("max_allowed_packet"), con.getServerVariable("max_allowed_packet"));
assertEquals(serverVariables.get("net_buffer_length"), con.getServerVariable("net_buffer_length"));
assertEquals(serverVariables.get("net_write_timeout"), con.getServerVariable("net_write_timeout"));
if (con.versionMeetsMinimum(8, 0, 3)) {
assertEquals(serverVariables.get("have_query_cache"), con.getServerVariable("have_query_cache"));
}
if (!con.versionMeetsMinimum(8, 0, 3) || "YES".equalsIgnoreCase(serverVariables.get("have_query_cache"))) {
if (!con.versionMeetsMinimum(8, 0, 3)) {
assertEquals(serverVariables.get("query_cache_size"), con.getServerVariable("query_cache_size"));
assertEquals(serverVariables.get("query_cache_type"), con.getServerVariable("query_cache_type"));
}
Expand All @@ -7606,11 +7609,7 @@ public void testBug75592() throws Exception {

assertEquals(serverVariables.get("system_time_zone"), con.getServerVariable("system_time_zone"));
assertEquals(serverVariables.get("time_zone"), con.getServerVariable("time_zone"));
if (con.versionMeetsMinimum(8, 0, 3)) {
assertEquals(serverVariables.get("transaction_isolation"), con.getServerVariable("transaction_isolation"));
} else {
assertEquals(serverVariables.get("tx_isolation"), con.getServerVariable("tx_isolation"));
}
assertEquals(serverVariables.get("transaction_isolation"), con.getServerVariable("transaction_isolation"));
assertEquals(serverVariables.get("wait_timeout"), con.getServerVariable("wait_timeout"));
if (!versionMeetsMinimum(5, 5, 0)) {
assertEquals(serverVariables.get("language"), con.getServerVariable("language"));
Expand Down Expand Up @@ -10232,4 +10231,44 @@ public void testBug79612() throws Exception {
}

}

/**
* Tests fix for Bug#88227 (27029657), Connector/J 5.1.44 cannot be used against MySQL 5.7.20 without warnings.
*/
public void testBug88227() throws Exception {
java.sql.Connection testConn = getConnectionWithProps("statementInterceptors=" + Bug88227StatementInterceptor.class.getName());
Bug88227StatementInterceptor.mayHaveWarnings = false;
testConn.getTransactionIsolation();
testConn.isReadOnly();
testConn.close();
}

public static class Bug88227StatementInterceptor implements StatementInterceptorV2 {
public static boolean mayHaveWarnings = true;

public void init(com.mysql.jdbc.Connection conn, Properties props) throws SQLException {
}

public boolean executeTopLevelOnly() {
return false;
}

public ResultSetInternalMethods preProcess(String sql, com.mysql.jdbc.Statement interceptedStatement, com.mysql.jdbc.Connection connection)
throws SQLException {
assertFalse("Unexpected [SHOW WARNINGS] was issued", sql.contains("SHOW WARNINGS"));
return null;
}

public ResultSetInternalMethods postProcess(String sql, com.mysql.jdbc.Statement interceptedStatement, ResultSetInternalMethods originalResultSet,
com.mysql.jdbc.Connection connection, int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, SQLException statementException)
throws SQLException {
if (!mayHaveWarnings) {
assertEquals("Warnings while executing [" + sql + "]", 0, warningCount);
}
return originalResultSet;
}

public void destroy() {
}
}
}
14 changes: 12 additions & 2 deletions src/testsuite/simple/ConnectionTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
Expand Down Expand Up @@ -56,6 +56,7 @@
import java.util.concurrent.Callable;

import com.mysql.jdbc.CharsetMapping;
import com.mysql.jdbc.ConnectionProperties;
import com.mysql.jdbc.MySQLConnection;
import com.mysql.jdbc.NonRegisteringDriver;
import com.mysql.jdbc.ResultSetInternalMethods;
Expand Down Expand Up @@ -529,14 +530,23 @@ public void testCharsets() throws Exception {
*/
public void testIsolationLevel() throws Exception {
if (versionMeetsMinimum(4, 0)) {
// Check initial transaction isolation level
((ConnectionProperties) this.conn).setUseLocalSessionState(true);
int initialTransactionIsolation = this.conn.getTransactionIsolation();

((ConnectionProperties) this.conn).setUseLocalSessionState(false);
int actualTransactionIsolation = this.conn.getTransactionIsolation();

assertEquals("Inital transaction isolation level doesn't match the server's", actualTransactionIsolation, initialTransactionIsolation);

// Check setting all allowed transaction isolation levels
String[] isoLevelNames = new String[] { "Connection.TRANSACTION_NONE", "Connection.TRANSACTION_READ_COMMITTED",
"Connection.TRANSACTION_READ_UNCOMMITTED", "Connection.TRANSACTION_REPEATABLE_READ", "Connection.TRANSACTION_SERIALIZABLE" };

int[] isolationLevels = new int[] { Connection.TRANSACTION_NONE, Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_READ_UNCOMMITTED,
Connection.TRANSACTION_REPEATABLE_READ, Connection.TRANSACTION_SERIALIZABLE };

DatabaseMetaData dbmd = this.conn.getMetaData();

for (int i = 0; i < isolationLevels.length; i++) {
if (dbmd.supportsTransactionIsolationLevel(isolationLevels[i])) {
this.conn.setTransactionIsolation(isolationLevels[i]);
Expand Down

0 comments on commit 2c80333

Please sign in to comment.