Skip to content

Commit 4f70ec3

Browse files
committed
Fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - autocommit status lost if global autocommit = 0.
Change-Id: I7a25b35b4040d2a075c2aba5b47f078c6a33a73e
1 parent 71e4c6b commit 4f70ec3

File tree

8 files changed

+70
-18
lines changed

8 files changed

+70
-18
lines changed

CHANGES

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.2.0
55

6+
- Fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - autocommit status lost if global autocommit = 0.
7+
68
- WL#15197, Support WebauthN in fido authentication plugin.
79

810
- Fix for Bug#107215 (Bug#34139593), ClassCastException: java.time.LocalDateTime cannot be cast to java.sql.Timestamp.

src/main/core-api/java/com/mysql/cj/CharsetSettings.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ public interface CharsetSettings {
5454
* </ol>
5555
* otherwise it will be set to utf8mb4_general_ci or utf8mb4_0900_ai_ci depending on server version.
5656
* <p>
57-
* Since Protocol::HandshakeV10 and Protocol::HandshakeResponse41 has only one byte for the collation it's not possible to use indexes &gt; 255 during the
57+
* Since Protocol::HandshakeV10 and Protocol::HandshakeResponse41 use only one byte for the collation it's not possible to use indexes &gt; 255 during the
5858
* handshake.
5959
* Also, ucs2, utf16, utf16le and utf32 character sets are impermissible here. Connector/J will try to use utf8mb4 instead.
6060
* </p>
6161
*
6262
* @param reset
63-
* reset the charsets configuration; needed for changeUser call.
63+
* reset the charsets configuration; needed for changeUser and resetServerState call.
6464
*
6565
* @return MySQL collation index to be used during the handshake.
6666
*/

src/main/core-impl/java/com/mysql/cj/NativeCharsetSettings.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,11 @@ public int configurePreHandshake(boolean reset) {
218218
&& (encoding = this.characterEncoding.getValue()) == null) {
219219
// If none of "passwordCharacterEncoding", "connectionCollation" or "characterEncoding" is specified then use UTF-8.
220220
// It would be better to use the server default collation here, to avoid unnecessary SET NAMES queries after the handshake if server
221-
// 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,
222-
// if the server is started with character-set-server=utf8mb4 and collation-server=utf8mb4_is_0900_ai_ci (collation index 257) the Protocol::HandshakeV10
223-
// 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,
224-
// but also other server series would be affected when configured with custom collations, for which the reserved collation id range is >= 1024.
221+
// 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
222+
// example, if the server is started with character-set-server=utf8mb4 and collation-server=utf8mb4_is_0900_ai_ci (collation index 257) the
223+
// Protocol::HandshakeV10 will contain character_set=1, "big5_chinese_ci". This is true not only for MySQL 8.0, where built-in collations with
224+
// indexes > 255 were first introduced, but also other server series would be affected when configured with custom collations, for which the
225+
// reserved collation id range is >= 1024.
225226
this.sessionCollationIndex = MYSQL_COLLATION_INDEX_utf8mb4_0900_ai_ci;
226227
}
227228
}

src/main/core-impl/java/com/mysql/cj/NativeSession.java

+6
Original file line numberDiff line numberDiff line change
@@ -827,4 +827,10 @@ public synchronized Timer getCancelTimer() {
827827
return this.cancelTimer;
828828
}
829829

830+
public void resetSessionState() {
831+
checkClosed();
832+
NativePacketPayload message = this.commandBuilder.buildComResetConnection(((NativeProtocol) this.protocol).getSharedSendPacket());
833+
this.protocol.sendCommand(message, false, 0);
834+
}
835+
830836
}

src/main/protocol-impl/java/com/mysql/cj/protocol/a/NativeMessageBuilder.java

+6
Original file line numberDiff line numberDiff line change
@@ -360,4 +360,10 @@ public NativePacketPayload buildComStmtExecute(NativePacketPayload sharedPacket,
360360
return packet;
361361
}
362362

363+
public NativePacketPayload buildComResetConnection(NativePacketPayload sharedPacket) {
364+
NativePacketPayload packet = sharedPacket != null ? sharedPacket : new NativePacketPayload(1);
365+
packet.writeInteger(IntegerDataType.INT1, NativeConstants.COM_RESET_CONNECTION);
366+
return packet;
367+
}
368+
363369
}

src/main/user-impl/java/com/mysql/cj/jdbc/ConnectionImpl.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,8 @@ public void changeUser(String userName, String newPassword) throws SQLException
545545
this.password = newPassword;
546546

547547
this.session.getServerSession().getCharsetSettings().configurePostHandshake(true);
548-
549548
this.session.setSessionVariables();
550-
549+
handleAutoCommitDefaults();
551550
setupServerForTruncationChecks();
552551
}
553552
}
@@ -1749,7 +1748,12 @@ public void releaseSavepoint(Savepoint arg0) throws SQLException {
17491748
@Override
17501749
public void resetServerState() throws SQLException {
17511750
if (!this.propertySet.getBooleanProperty(PropertyKey.paranoid).getValue() && this.session != null) {
1752-
changeUser(this.user, this.password);
1751+
this.session.getServerSession().getCharsetSettings().configurePreHandshake(true);
1752+
this.session.resetSessionState();
1753+
this.session.getServerSession().getCharsetSettings().configurePostHandshake(true);
1754+
this.session.setSessionVariables();
1755+
handleAutoCommitDefaults();
1756+
setupServerForTruncationChecks();
17531757
}
17541758
}
17551759

src/test/java/testsuite/regression/DataSourceRegressionTest.java

+39-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ public void testBug72632() throws Exception {
577577
* @throws Exception
578578
*/
579579
@Test
580-
void testBug104954() throws Exception {
580+
public void testBug104954() throws Exception {
581581
createDatabase("testBug104954");
582582
createDatabase("`testBug104954?bug=104954`");
583583

@@ -604,4 +604,42 @@ void testBug104954() throws Exception {
604604
}
605605
}
606606

607+
/**
608+
* Tests fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - autocommit status lost if global autocommit = 0.
609+
*
610+
* @throws Exception
611+
*/
612+
@Test
613+
public void testBug91351() throws Exception {
614+
try {
615+
createTable("testBug91351", "(txt VARCHAR(100))");
616+
this.stmt.executeUpdate("SET GLOBAL autocommit=0"); // Pre-condition: global autocommit=0.
617+
618+
final String testDbUrl = dbUrl + (dbUrl.contains("?") ? "&" : "?");
619+
boolean isParanoid = false;
620+
do {
621+
MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();
622+
ds.setUrl(testDbUrl + "paranoid=" + isParanoid);
623+
Connection testConn = ds.getPooledConnection().getConnection();
624+
testConn.createStatement().execute("SET SESSION wait_timeout=5"); // Otherwise test would hang when tearing down created artifacts.
625+
626+
PreparedStatement testPstmt = null;
627+
String query = "INSERT INTO testBug91351 VALUES (?)";
628+
testPstmt = testConn.prepareStatement(query);
629+
testPstmt.setString(1, "MySQL Connector/J");
630+
testPstmt.executeUpdate();
631+
632+
testConn.close();
633+
634+
this.rs = this.stmt.executeQuery("SELECT * FROM testBug91351");
635+
assertTrue(this.rs.next());
636+
assertEquals("MySQL Connector/J", this.rs.getString(1));
637+
638+
testConn.close();
639+
} while (isParanoid = !isParanoid);
640+
} finally {
641+
this.stmt.executeUpdate("SET GLOBAL autocommit=1");
642+
}
643+
}
644+
607645
}

src/test/java/testsuite/simple/DataSourceTest.java

+3-8
Original file line numberDiff line numberDiff line change
@@ -158,27 +158,22 @@ public void testChangeUserAndCharsets() throws Exception {
158158
Connection connToMySQL = pooledConnection.getConnection();
159159
this.rs = connToMySQL.createStatement().executeQuery("SELECT @@character_set_results");
160160
assertTrue(this.rs.next());
161-
162161
assertNull(this.rs.getString(1));
163162

164163
this.rs = connToMySQL.createStatement().executeQuery("SHOW SESSION VARIABLES LIKE 'character_set_client'");
165164
assertTrue(this.rs.next());
166-
167-
// Because of utf8mb4
168-
assertTrue(this.rs.getString(2).startsWith("utf8"));
165+
assertTrue(this.rs.getString(2).startsWith("utf8")); // Because of utf8mb4.
169166

170167
connToMySQL.close();
171168

172169
connToMySQL = pooledConnection.getConnection();
173170
this.rs = connToMySQL.createStatement().executeQuery("SELECT @@character_set_results");
174171
assertTrue(this.rs.next());
175-
assertEquals(null, this.rs.getString(1));
172+
assertNull(this.rs.getString(1));
176173

177174
this.rs = connToMySQL.createStatement().executeQuery("SHOW SESSION VARIABLES LIKE 'character_set_client'");
178175
assertTrue(this.rs.next());
179-
180-
// Because of utf8mb4
181-
assertTrue(this.rs.getString(2).startsWith("utf8"));
176+
assertTrue(this.rs.getString(2).startsWith("utf8")); // Because of utf8mb4.
182177

183178
pooledConnection.getConnection().close();
184179
}

0 commit comments

Comments
 (0)