Skip to content

Commit

Permalink
Fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - aut…
Browse files Browse the repository at this point in the history
…ocommit status lost if global autocommit = 0.

Change-Id: I7a25b35b4040d2a075c2aba5b47f078c6a33a73e
  • Loading branch information
fjssilva committed Sep 5, 2023
1 parent 71e4c6b commit 4f70ec3
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 18 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 8.2.0

- Fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - autocommit status lost if global autocommit = 0.

- WL#15197, Support WebauthN in fido authentication plugin.

- Fix for Bug#107215 (Bug#34139593), ClassCastException: java.time.LocalDateTime cannot be cast to java.sql.Timestamp.
Expand Down
4 changes: 2 additions & 2 deletions src/main/core-api/java/com/mysql/cj/CharsetSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ public interface CharsetSettings {
* </ol>
* otherwise it will be set to utf8mb4_general_ci or utf8mb4_0900_ai_ci depending on server version.
* <p>
* Since Protocol::HandshakeV10 and Protocol::HandshakeResponse41 has only one byte for the collation it's not possible to use indexes &gt; 255 during the
* Since Protocol::HandshakeV10 and Protocol::HandshakeResponse41 use only one byte for the collation it's not possible to use indexes &gt; 255 during the
* handshake.
* Also, ucs2, utf16, utf16le and utf32 character sets are impermissible here. Connector/J will try to use utf8mb4 instead.
* </p>
*
* @param reset
* reset the charsets configuration; needed for changeUser call.
* reset the charsets configuration; needed for changeUser and resetServerState call.
*
* @return MySQL collation index to be used during the handshake.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,11 @@ public int configurePreHandshake(boolean reset) {
&& (encoding = this.characterEncoding.getValue()) == null) {
// If none of "passwordCharacterEncoding", "connectionCollation" or "characterEncoding" is specified then use UTF-8.
// It would be better to use the server default collation here, to avoid unnecessary SET NAMES queries after the handshake if server
// default charset if not utf8, but we can not do it until server Bug#32729185 is fixed. Server cuts collation index to lower byte and, for example,
// if the server is started with character-set-server=utf8mb4 and collation-server=utf8mb4_is_0900_ai_ci (collation index 257) the Protocol::HandshakeV10
// will contain character_set=1, "big5_chinese_ci". This is true not only for MySQL 8.0, where built-in collations with indexes > 255 were first introduced,
// but also other server series would be affected when configured with custom collations, for which the reserved collation id range is >= 1024.
// default charset if not utf8, but we can not do it until server Bug#32729185 is fixed. Server cuts collation index to lower byte and, for
// example, if the server is started with character-set-server=utf8mb4 and collation-server=utf8mb4_is_0900_ai_ci (collation index 257) the
// Protocol::HandshakeV10 will contain character_set=1, "big5_chinese_ci". This is true not only for MySQL 8.0, where built-in collations with
// indexes > 255 were first introduced, but also other server series would be affected when configured with custom collations, for which the
// reserved collation id range is >= 1024.
this.sessionCollationIndex = MYSQL_COLLATION_INDEX_utf8mb4_0900_ai_ci;
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/core-impl/java/com/mysql/cj/NativeSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -827,4 +827,10 @@ public synchronized Timer getCancelTimer() {
return this.cancelTimer;
}

public void resetSessionState() {
checkClosed();
NativePacketPayload message = this.commandBuilder.buildComResetConnection(((NativeProtocol) this.protocol).getSharedSendPacket());
this.protocol.sendCommand(message, false, 0);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,10 @@ public NativePacketPayload buildComStmtExecute(NativePacketPayload sharedPacket,
return packet;
}

public NativePacketPayload buildComResetConnection(NativePacketPayload sharedPacket) {
NativePacketPayload packet = sharedPacket != null ? sharedPacket : new NativePacketPayload(1);
packet.writeInteger(IntegerDataType.INT1, NativeConstants.COM_RESET_CONNECTION);
return packet;
}

}
10 changes: 7 additions & 3 deletions src/main/user-impl/java/com/mysql/cj/jdbc/ConnectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,8 @@ public void changeUser(String userName, String newPassword) throws SQLException
this.password = newPassword;

this.session.getServerSession().getCharsetSettings().configurePostHandshake(true);

this.session.setSessionVariables();

handleAutoCommitDefaults();
setupServerForTruncationChecks();
}
}
Expand Down Expand Up @@ -1749,7 +1748,12 @@ public void releaseSavepoint(Savepoint arg0) throws SQLException {
@Override
public void resetServerState() throws SQLException {
if (!this.propertySet.getBooleanProperty(PropertyKey.paranoid).getValue() && this.session != null) {
changeUser(this.user, this.password);
this.session.getServerSession().getCharsetSettings().configurePreHandshake(true);
this.session.resetSessionState();
this.session.getServerSession().getCharsetSettings().configurePostHandshake(true);
this.session.setSessionVariables();
handleAutoCommitDefaults();
setupServerForTruncationChecks();
}
}

Expand Down
40 changes: 39 additions & 1 deletion src/test/java/testsuite/regression/DataSourceRegressionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ public void testBug72632() throws Exception {
* @throws Exception
*/
@Test
void testBug104954() throws Exception {
public void testBug104954() throws Exception {
createDatabase("testBug104954");
createDatabase("`testBug104954?bug=104954`");

Expand All @@ -604,4 +604,42 @@ void testBug104954() throws Exception {
}
}

/**
* Tests fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - autocommit status lost if global autocommit = 0.
*
* @throws Exception
*/
@Test
public void testBug91351() throws Exception {
try {
createTable("testBug91351", "(txt VARCHAR(100))");
this.stmt.executeUpdate("SET GLOBAL autocommit=0"); // Pre-condition: global autocommit=0.

final String testDbUrl = dbUrl + (dbUrl.contains("?") ? "&" : "?");
boolean isParanoid = false;
do {
MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();
ds.setUrl(testDbUrl + "paranoid=" + isParanoid);
Connection testConn = ds.getPooledConnection().getConnection();
testConn.createStatement().execute("SET SESSION wait_timeout=5"); // Otherwise test would hang when tearing down created artifacts.

PreparedStatement testPstmt = null;
String query = "INSERT INTO testBug91351 VALUES (?)";
testPstmt = testConn.prepareStatement(query);
testPstmt.setString(1, "MySQL Connector/J");
testPstmt.executeUpdate();

testConn.close();

this.rs = this.stmt.executeQuery("SELECT * FROM testBug91351");
assertTrue(this.rs.next());
assertEquals("MySQL Connector/J", this.rs.getString(1));

testConn.close();
} while (isParanoid = !isParanoid);
} finally {
this.stmt.executeUpdate("SET GLOBAL autocommit=1");
}
}

}
11 changes: 3 additions & 8 deletions src/test/java/testsuite/simple/DataSourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,27 +158,22 @@ public void testChangeUserAndCharsets() throws Exception {
Connection connToMySQL = pooledConnection.getConnection();
this.rs = connToMySQL.createStatement().executeQuery("SELECT @@character_set_results");
assertTrue(this.rs.next());

assertNull(this.rs.getString(1));

this.rs = connToMySQL.createStatement().executeQuery("SHOW SESSION VARIABLES LIKE 'character_set_client'");
assertTrue(this.rs.next());

// Because of utf8mb4
assertTrue(this.rs.getString(2).startsWith("utf8"));
assertTrue(this.rs.getString(2).startsWith("utf8")); // Because of utf8mb4.

connToMySQL.close();

connToMySQL = pooledConnection.getConnection();
this.rs = connToMySQL.createStatement().executeQuery("SELECT @@character_set_results");
assertTrue(this.rs.next());
assertEquals(null, this.rs.getString(1));
assertNull(this.rs.getString(1));

this.rs = connToMySQL.createStatement().executeQuery("SHOW SESSION VARIABLES LIKE 'character_set_client'");
assertTrue(this.rs.next());

// Because of utf8mb4
assertTrue(this.rs.getString(2).startsWith("utf8"));
assertTrue(this.rs.getString(2).startsWith("utf8")); // Because of utf8mb4.

pooledConnection.getConnection().close();
}
Expand Down

0 comments on commit 4f70ec3

Please sign in to comment.