Skip to content

Commit a281379

Browse files
committed
Fix for Bug#118002 (Bug#37843004), The setFetchSize() method in the Statement class may have a potential bug.
Change-Id: Id83b5d9953bb5633f51889deff570e011ffd5396
1 parent 5767fc5 commit a281379

6 files changed

Lines changed: 79 additions & 34 deletions

File tree

CHANGES

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

44
Version 9.6.0
55

6+
- Fix for Bug#118002 (Bug#37843004), The setFetchSize() method in the Statement class may have a potential bug.
7+
68
- Fix for Bug#113130 (Bug#36043125), getGeneratedKeys() returns a zero resultset with non-key-generating statements.
79

810
- Fix for Bug#113336 (Bug#36080226), Inconsistent getUpdateCount() Behavior with allowMultiQueries.

src/main/resources/com/mysql/cj/LocalizedErrorMessages.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ ResultSet.Illegal_operation_on_empty_result_set=Illegal operation on empty resul
454454
ResultSet.Query_generated_no_fields_for_ResultSet_57=Query generated no fields for ResultSet
455455
ResultSet.Illegal_value_for_fetch_direction_64=Illegal value for fetch direction
456456
ResultSet.Unacceptable_value_for_fetch_direction=Fetch direction {0} cannot be set on a ResultSet of type ResultSet.TYPE_FORWARD_ONLY
457-
ResultSet.Value_must_be_between_0_and_getMaxRows()_66=Value must be between 0 and getMaxRows()
457+
ResultSet.Value_out_of_range_66=Value out of range.
458458
ResultSet.Query_generated_no_fields_for_ResultSet_99=Query generated no fields for ResultSet
459459
ResultSet.Operation_not_allowed_after_ResultSet_closed_144=Operation not allowed after ResultSet closed
460460
ResultSet.Before_start_of_result_set_146=Before start of result set
@@ -610,7 +610,7 @@ Statement.5=Illegal value for setFetchDirection().
610610
Statement.7=Illegal value for setFetchSize().
611611
Statement.11=Illegal value for setMaxFieldSize().
612612
Statement.13=Can not set max field size > max allowed packet of {0} bytes.
613-
Statement.15=setMaxRows() out of range.
613+
Statement.15=setMaxRows() out of range.
614614
Statement.19=Illegal flag for getMoreResults(int).
615615
Statement.21=Illegal value for setQueryTimeout().
616616
Statement.27=Connection is read-only.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,7 @@ public void setFetchSize(int rows) throws SQLException {
20132013
Lock connectionLock = checkClosed().getConnectionLock();
20142014
connectionLock.lock();
20152015
try {
2016-
if (rows < 0 && rows != Integer.MIN_VALUE || this.maxRows > 0 && rows > getMaxRows()) {
2016+
if (rows < 0 && rows != Integer.MIN_VALUE) {
20172017
throw SQLError.createSQLException(Messages.getString("Statement.7"), MysqlErrorNumbers.SQLSTATE_CONNJ_ILLEGAL_ARGUMENT,
20182018
getExceptionInterceptor());
20192019
}
@@ -2345,7 +2345,7 @@ public void setLargeMaxRows(long max) throws SQLException {
23452345
connectionLock.lock();
23462346
try {
23472347
if (max > MAX_ROWS || max < 0) {
2348-
throw SQLError.createSQLException(Messages.getString("Statement.15") + max + (max > MAX_ROWS ? " > " + MAX_ROWS : " < 0") + ".",
2348+
throw SQLError.createSQLException(Messages.getString("Statement.15") + " " + max + (max > MAX_ROWS ? " > " + MAX_ROWS : " < 0") + ".",
23492349
MysqlErrorNumbers.SQLSTATE_CONNJ_ILLEGAL_ARGUMENT, getExceptionInterceptor());
23502350
}
23512351

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,9 +2095,9 @@ public void setFetchSize(int rows) throws SQLException {
20952095
Lock connectionLock = checkClosed().getConnectionLock();
20962096
connectionLock.lock();
20972097
try {
2098-
if (rows < 0 && rows != Integer.MIN_VALUE) { /* || rows > getMaxRows() */
2099-
throw SQLError.createSQLException(Messages.getString("ResultSet.Value_must_be_between_0_and_getMaxRows()_66"),
2100-
MysqlErrorNumbers.SQLSTATE_CONNJ_ILLEGAL_ARGUMENT, getExceptionInterceptor());
2098+
if (rows < 0 && rows != Integer.MIN_VALUE) {
2099+
throw SQLError.createSQLException(Messages.getString("ResultSet.Value_out_of_range_66"), MysqlErrorNumbers.SQLSTATE_CONNJ_ILLEGAL_ARGUMENT,
2100+
getExceptionInterceptor());
21012101
}
21022102

21032103
this.fetchSize = rows;

src/test/java/testsuite/regression/StatementRegressionTest.java

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14712,6 +14712,8 @@ public void testBug113336() throws Exception {
1471214712

1471314713
boolean rwBS = false;
1471414714
do {
14715+
String testCase = String.format("Case [rwBS: %s]", rwBS ? "Y" : "N");
14716+
1471514717
Properties props = new Properties();
1471614718
props.setProperty(PropertyKey.allowMultiQueries.getKeyName(), "true");
1471714719
props.setProperty(PropertyKey.rewriteBatchedStatements.getKeyName(), Boolean.toString(rwBS));
@@ -14723,27 +14725,27 @@ public void testBug113336() throws Exception {
1472314725
testStmt.addBatch("INSERT INTO testBug113336 VALUES (1, 'Data1')");
1472414726
testStmt.addBatch("INSERT INTO testBug113336 VALUES (2, 'Data2'), (3, 'Data3')");
1472514727
updCounts = testStmt.executeBatch();
14726-
assertArrayEquals(new int[] { 1, 2 }, updCounts);
14727-
assertEquals(2, testStmt.getUpdateCount());
14728+
assertArrayEquals(new int[] { 1, 2 }, updCounts, testCase);
14729+
assertEquals(2, testStmt.getUpdateCount(), testCase);
1472814730

1472914731
updCount = testStmt.executeUpdate("UPDATE testBug113336 SET txt=UPPER(txt) WHERE id=1; DELETE FROM testBug113336 WHERE id = 0; "
1473014732
+ "UPDATE testBug113336 SET txt=LOWER(txt) WHERE id >= 2"); // UpdateCount: {1, 0, 2}
1473114733
// It might be that the right updateCount should be 2 (the update count from the last query), but this is not how it currently works.
14732-
assertEquals(1, updCount);
14733-
assertEquals(1, testStmt.getUpdateCount());
14734+
assertEquals(1, updCount, testCase);
14735+
assertEquals(1, testStmt.getUpdateCount(), testCase);
1473414736

1473514737
testStmt.addBatch("UPDATE testBug113336 SET txt=UPPER(txt) WHERE id <= 2");
1473614738
testStmt.addBatch("DELETE FROM testBug113336 WHERE id = 1");
1473714739
testStmt.addBatch("INSERT INTO testBug113336 VALUES (4, 'Data4')");
1473814740
testStmt.addBatch("DELETE FROM testBug113336 WHERE id <= 3");
1473914741
testStmt.addBatch("INSERT INTO testBug113336 VALUES (5, 'Data5'), (6, 'Data6'), (7, 'Data7')");
1474014742
updCounts = testStmt.executeBatch();
14741-
assertArrayEquals(new int[] { 2, 1, 1, 2, 3 }, updCounts);
14742-
assertEquals(3, testStmt.getUpdateCount());
14743+
assertArrayEquals(new int[] { 2, 1, 1, 2, 3 }, updCounts, testCase);
14744+
assertEquals(3, testStmt.getUpdateCount(), testCase);
1474314745

1474414746
updCount = testStmt.executeUpdate("TRUNCATE TABLE testBug113336");
14745-
assertEquals(0, updCount);
14746-
assertEquals(0, testStmt.getUpdateCount());
14747+
assertEquals(0, updCount, testCase);
14748+
assertEquals(0, testStmt.getUpdateCount(), testCase);
1474714749
}
1474814750
} while (rwBS = !rwBS);
1474914751
}
@@ -14761,6 +14763,8 @@ public void testBug113130() throws SQLException {
1476114763
boolean allowMQ = false;
1476214764
boolean rwBS = false;
1476314765
do {
14766+
String testCase = String.format("Case [allowMQ: %s, rwBS: %s]", allowMQ ? "Y" : "N", rwBS ? "Y" : "N");
14767+
1476414768
Properties props = new Properties();
1476514769
props.setProperty(PropertyKey.allowMultiQueries.getKeyName(), Boolean.toString(allowMQ));
1476614770
props.setProperty(PropertyKey.rewriteBatchedStatements.getKeyName(), Boolean.toString(rwBS));
@@ -14772,12 +14776,12 @@ public void testBug113130() throws SQLException {
1477214776
testStmt.addBatch(String.format("INSERT INTO testBug113130NoAI VALUES (%d, 'Data%d')", i, i));
1477314777
}
1477414778
int updCounts[] = testStmt.executeBatch();
14775-
assertEquals(q, updCounts.length);
14779+
assertEquals(q, updCounts.length, testCase);
1477614780
for (int i = 0; i < q; i++) {
14777-
assertEquals(1, updCounts[i]);
14781+
assertEquals(1, updCounts[i], testCase);
1477814782
}
1477914783
this.rs = testStmt.getGeneratedKeys();
14780-
assertFalse(this.rs.next());
14784+
assertFalse(this.rs.next(), testCase);
1478114785
}
1478214786

1478314787
try (Connection testConn = getConnectionWithProps(props)) {
@@ -14786,16 +14790,16 @@ public void testBug113130() throws SQLException {
1478614790
testStmt.addBatch(String.format("INSERT INTO testBug113130AI (data) VALUES ('Data%d')", i));
1478714791
}
1478814792
int updCounts[] = testStmt.executeBatch();
14789-
assertEquals(q, updCounts.length);
14793+
assertEquals(q, updCounts.length, testCase);
1479014794
for (int i = 0; i < q; i++) {
14791-
assertEquals(1, updCounts[i]);
14795+
assertEquals(1, updCounts[i], testCase);
1479214796
}
1479314797
this.rs = testStmt.getGeneratedKeys();
1479414798
for (int i = 1; i <= q; i++) {
14795-
assertTrue(this.rs.next());
14796-
assertEquals(i, this.rs.getInt(1));
14799+
assertTrue(this.rs.next(), testCase);
14800+
assertEquals(i, this.rs.getInt(1), testCase);
1479714801
}
14798-
assertFalse(this.rs.next());
14802+
assertFalse(this.rs.next(), testCase);
1479914803
}
1480014804

1480114805
this.stmt.execute("TRUNCATE TABLE testBug113130NoAI");
@@ -14805,4 +14809,52 @@ public void testBug113130() throws SQLException {
1480514809
} while ((allowMQ = !allowMQ) || (rwBS = !rwBS));
1480614810
}
1480714811

14812+
/**
14813+
* Tests fix for Bug#118002 (Bug#37843004), The setFetchSize() method in the Statement class may have a potential bug.
14814+
*
14815+
* @throws Exception
14816+
*/
14817+
@Test
14818+
void testBug118002() throws Exception {
14819+
assumeTrue(versionMeetsMinimum(8, 1), "MySQL 8.1+ is required to run this test.");
14820+
14821+
createTable("testBug118002", "(id INT)");
14822+
assertEquals(100, this.stmt.executeUpdate(
14823+
"INSERT INTO testBug118002 (id) WITH RECURSIVE nums AS (SELECT 1 AS n UNION ALL SELECT n + 1 FROM nums WHERE n < 100) SELECT n FROM nums"));
14824+
14825+
boolean useCF = false;
14826+
boolean useSPS = false;
14827+
do {
14828+
String testCase = String.format("Case [useCF: %s, useSPS: %s]", useCF ? "Y" : "N", useSPS ? "Y" : "N");
14829+
14830+
Properties props = new Properties();
14831+
props.setProperty(PropertyKey.useCursorFetch.getKeyName(), Boolean.toString(useCF));
14832+
props.setProperty(PropertyKey.useServerPrepStmts.getKeyName(), Boolean.toString(useSPS));
14833+
14834+
try (Connection testConn = getConnectionWithProps(props)) {
14835+
Statement testStmt = testConn.createStatement();
14836+
testStmt.setMaxRows(10);
14837+
assertEquals(10, testStmt.getMaxRows(), testCase);
14838+
testStmt.setFetchSize(50);
14839+
assertEquals(50, testStmt.getFetchSize(), testCase);
14840+
this.rs = testStmt.executeQuery("SELECT * FROM testBug118002");
14841+
for (int i = 1; i <= 10; i++) {
14842+
assertTrue(this.rs.next(), testCase);
14843+
assertEquals(i, this.rs.getInt(1), testCase);
14844+
}
14845+
assertFalse(this.rs.next(), testCase);
14846+
14847+
PreparedStatement testPStmt = testConn.prepareStatement("SELECT * FROM testBug118002");
14848+
testPStmt.setMaxRows(12);
14849+
testPStmt.setFetchSize(60);
14850+
this.rs = testPStmt.executeQuery();
14851+
for (int i = 1; i <= 12; i++) {
14852+
assertTrue(this.rs.next(), testCase);
14853+
assertEquals(i, this.rs.getInt(1), testCase);
14854+
}
14855+
assertFalse(this.rs.next(), testCase);
14856+
}
14857+
} while ((useCF = !useCF) || (useSPS = !useSPS));
14858+
}
14859+
1480814860
}

src/test/java/testsuite/simple/StatementsTest.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,7 @@ public void testAccessorsAndMutators() throws SQLException {
117117
accessorStmt.setEscapeProcessing(true);
118118
accessorStmt.setFetchDirection(java.sql.ResultSet.FETCH_FORWARD);
119119

120-
int fetchDirection = accessorStmt.getFetchDirection();
121-
assertTrue(fetchDirection == java.sql.ResultSet.FETCH_FORWARD, "Set fetch direction != get fetch direction");
120+
assertEquals(java.sql.ResultSet.FETCH_FORWARD, accessorStmt.getFetchDirection(), "Set fetch direction != get fetch direction");
122121

123122
assertThrows("Should not be able to set fetch direction to invalid value", SQLException.class, () -> {
124123
accessorStmt.setFetchDirection(Integer.MAX_VALUE);
@@ -136,19 +135,11 @@ public void testAccessorsAndMutators() throws SQLException {
136135
});
137136

138137
int fetchSize = this.stmt.getFetchSize();
139-
140-
accessorStmt.setMaxRows(4);
141-
assertThrows("Should not be able to set FetchSize > max rows", SQLException.class, () -> {
142-
accessorStmt.setFetchSize(Integer.MAX_VALUE);
143-
return null;
144-
});
145-
146138
assertThrows("Should not be able to set FetchSize < 0", SQLException.class, () -> {
147139
accessorStmt.setFetchSize(-2);
148140
return null;
149141
});
150-
151-
assertTrue(fetchSize == this.stmt.getFetchSize(), "Fetch size before invalid setFetchSize() calls should match fetch size now");
142+
assertEquals(fetchSize, this.stmt.getFetchSize(), "Fetch size before invalid setFetchSize() calls should match fetch size now");
152143
}
153144

154145
@Test

0 commit comments

Comments
 (0)