Description:
When useCursorFetch=true is enabled (forcing the use of the Binary Protocol), the MySQL JDBC Connector incorrectly decodes TIME values that represent negative durations exceeding 24 hours.
The root cause is a sign-handling error in MysqlBinaryValueDecoder.decodeTime. The driver correctly identifies the negative sign bit and negates the days component, but it fails to negate the residual hours component before adding them together.
For example, for the minimum MySQL TIME value -838:59:59:
The server sends: Negative=true, Days=34, Hours=22.
The buggy driver logic performs:
(-34 * 24) + 22
.
The resulting calculation is -816 + 22, which equals -794.
The value returned via ResultSet.getString() is shifted by exactly +44 hours (specifically +2 * residual_hours).
How to repeat:
Run a MySQL 8.0+ server.
Initialize a table: CREATE TABLE time_test (id INT PRIMARY KEY, time_col TIME);
Link a value: INSERT INTO time_test VALUES (1, '-838:59:59');
Run the following Java code using Connector/J (e.g., 9.6.0) with useCursorFetch=true:
```
// Setup connection with useCursorFetch=true
String url = "jdbc:mysql://localhost:3306/db?useCursorFetch=true";
Connection conn = DriverManager.getConnection(url, "user", "pass");
// Trigger Cursor Mode (Binary Protocol) by setting a fetch size
Statement stmt = conn.createStatement();
stmt.setFetchSize(10);
ResultSet rs = stmt.executeQuery("SELECT time_col FROM time_test WHERE id = 1");
if (rs.next()) {
System.out.println("Expected: -838:59:59");
System.out.println("Actual: " + rs.getString(1)); // Prints -794:59:59
}
```
Suggested fix:
In com.mysql.cj.protocol.a.MysqlBinaryValueDecoder.java, update the
decodeTime method to ensure the hours, minutes, etc components are treated as a negative offset when the negative flag is true.
Description: When useCursorFetch=true is enabled (forcing the use of the Binary Protocol), the MySQL JDBC Connector incorrectly decodes TIME values that represent negative durations exceeding 24 hours. The root cause is a sign-handling error in MysqlBinaryValueDecoder.decodeTime. The driver correctly identifies the negative sign bit and negates the days component, but it fails to negate the residual hours component before adding them together. For example, for the minimum MySQL TIME value -838:59:59: The server sends: Negative=true, Days=34, Hours=22. The buggy driver logic performs: (-34 * 24) + 22 . The resulting calculation is -816 + 22, which equals -794. The value returned via ResultSet.getString() is shifted by exactly +44 hours (specifically +2 * residual_hours). How to repeat: Run a MySQL 8.0+ server. Initialize a table: CREATE TABLE time_test (id INT PRIMARY KEY, time_col TIME); Link a value: INSERT INTO time_test VALUES (1, '-838:59:59'); Run the following Java code using Connector/J (e.g., 9.6.0) with useCursorFetch=true: ``` // Setup connection with useCursorFetch=true String url = "jdbc:mysql://localhost:3306/db?useCursorFetch=true"; Connection conn = DriverManager.getConnection(url, "user", "pass"); // Trigger Cursor Mode (Binary Protocol) by setting a fetch size Statement stmt = conn.createStatement(); stmt.setFetchSize(10); ResultSet rs = stmt.executeQuery("SELECT time_col FROM time_test WHERE id = 1"); if (rs.next()) { System.out.println("Expected: -838:59:59"); System.out.println("Actual: " + rs.getString(1)); // Prints -794:59:59 } ``` Suggested fix: In com.mysql.cj.protocol.a.MysqlBinaryValueDecoder.java, update the decodeTime method to ensure the hours, minutes, etc components are treated as a negative offset when the negative flag is true.