Skip to content

Commit 9aae1e4

Browse files
committed
Fix for Bug#32954396, EXECUTEQUERY HANGS WITH USECURSORFETCH=TRUE & SETFETCHSIZE.
1 parent f0f1a6a commit 9aae1e4

File tree

4 files changed

+41
-6
lines changed

4 files changed

+41
-6
lines changed

CHANGES

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
Version 8.0.26
55

6+
- Fix for Bug#32954396, EXECUTEQUERY HANGS WITH USECURSORFETCH=TRUE & SETFETCHSIZE.
7+
68
- Fix for Bug#102372 (32459408), v8.0.23 unusable in OSGi.
79

810
- Fix for Bug#25554464, CONNECT FAILS WITH NPE WHEN THE SERVER STARTED WITH CUSTOM COLLATION.

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,20 @@ public Resultset read(int maxRows, boolean streamResults, NativePacketPayload re
6969
// Read in the column information
7070
ColumnDefinition cdef = this.protocol.read(ColumnDefinition.class, new MergingColumnDefinitionFactory(columnCount, metadata));
7171

72-
boolean isCursorPosible = this.protocol.getPropertySet().getBooleanProperty(PropertyKey.useCursorFetch).getValue()
72+
boolean isCursorPossible = this.protocol.getPropertySet().getBooleanProperty(PropertyKey.useCursorFetch).getValue()
7373
&& resultSetFactory.getResultSetType() == Type.FORWARD_ONLY && resultSetFactory.getFetchSize() > 0;
7474

7575
// There is no EOF packet after fields when CLIENT_DEPRECATE_EOF is set;
76-
// if we asked to use cursor then there should be an OK packet here
77-
if (isCursorPosible || !this.protocol.getServerSession().isEOFDeprecated()) {
78-
this.protocol.readServerStatusForResultSets(this.protocol.readMessage(this.protocol.getReusablePacket()), true);
76+
// if we asked to use cursor then there should be an OK or an ERR packet here
77+
if (isCursorPossible || !this.protocol.getServerSession().isEOFDeprecated()) {
78+
NativePacketPayload rowPacket = this.protocol.readMessage(this.protocol.getReusablePacket());
79+
this.protocol.checkErrorMessage(rowPacket);
80+
this.protocol.readServerStatusForResultSets(rowPacket, true);
7981
}
8082

8183
ResultsetRows rows = null;
8284

83-
if (isCursorPosible && this.protocol.getServerSession().cursorExists()) {
85+
if (isCursorPossible && this.protocol.getServerSession().cursorExists()) {
8486
rows = new ResultsetRowsCursor(this.protocol, cdef);
8587

8688
} else if (!streamResults) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1661,7 +1661,7 @@ public final <T> T readServerStatusForResultSets(NativePacketPayload rowPacket,
16611661
T result = null;
16621662
if (rowPacket.isEOFPacket()) {
16631663
// read EOF packet
1664-
rowPacket.readInteger(IntegerDataType.INT1); // skips the 'last packet' flag (packet signature)
1664+
rowPacket.setPosition(1); // skip the packet signature header
16651665
this.warningCount = (int) rowPacket.readInteger(IntegerDataType.INT2);
16661666
if (this.warningCount > 0) {
16671667
this.hadWarnings = true; // this is a 'latch', it's reset by sendCommand()

src/test/java/testsuite/regression/ResultSetRegressionTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6979,6 +6979,7 @@ public Void call() throws Exception {
69796979
assertEquals('a', rs1.getBytes(2)[0]);
69806980
assertEquals('a', rs1.getByte(2));
69816981
assertThrows(SQLDataException.class, "Cannot determine value type from string 'a'", new Callable<Void>() {
6982+
69826983
public Void call() throws Exception {
69836984
rs1.getInt(2);
69846985
return null;
@@ -7074,6 +7075,7 @@ public Void call() throws Exception {
70747075
});
70757076
assertTrue(rs1.getString(5).startsWith("23"));
70767077
}
7078+
70777079
}
70787080
}
70797081

@@ -7947,4 +7949,33 @@ public void testBug20802947() throws Exception {
79477949
}
79487950
rs1.close();
79497951
}
7952+
7953+
/**
7954+
* Test fix for Bug#32954396, EXECUTEQUERY HANGS WITH USECURSORFETCH=TRUE & SETFETCHSIZE.
7955+
*
7956+
* @throws Exception
7957+
*/
7958+
@Test
7959+
public void testBug32954396() throws Exception {
7960+
createTable("testBug32954396", "(id INT, name VARCHAR(10))");
7961+
7962+
this.stmt.executeUpdate("INSERT INTO testBug32954396 VALUES (1, 'value1'), (2, 'value2')");
7963+
7964+
boolean useCursorFetch = false;
7965+
boolean setFetchSize = false;
7966+
do {
7967+
String testCase = String.format("Case: [useCursorFetch=%s, setFetchSize=%s]", useCursorFetch ? "Y" : "N", setFetchSize ? "Y" : "N");
7968+
Properties props = new Properties();
7969+
props.setProperty(PropertyKey.socketTimeout.getKeyName(), "1000");
7970+
props.setProperty(PropertyKey.useCursorFetch.getKeyName(), Boolean.toString(useCursorFetch));
7971+
Connection testConn = getConnectionWithProps(props);
7972+
7973+
this.pstmt = testConn.prepareStatement("SELECT id, name, (SELECT id FROM testBug32954396) FROM testBug32954396");
7974+
if (setFetchSize) {
7975+
this.pstmt.setFetchSize(1);
7976+
}
7977+
assertThrows(testCase, SQLException.class, "Subquery returns more than 1 row", this.pstmt::executeQuery);
7978+
testConn.close();
7979+
} while ((useCursorFetch = !useCursorFetch) || (setFetchSize = !setFetchSize));
7980+
}
79507981
}

0 commit comments

Comments
 (0)