Description:
With version 8.0.23 the ResultSetMetaData.getColumnClassName() no longer returns the actual class for DATETIME columns.
The output of the program below with the two different versions:
MySQL Connector/J version mysql-connector-java-8.0.22 (Revision: d64b664fa93e81296a377de031b8123a67e6def2)
DATE column 1 is expected type java.sql.Date
DATETIME column 2 is expected type java.sql.Timestamp
TIMESTAMP column 3 is expected type java.sql.Timestamp
MySQL Connector/J version mysql-connector-java-8.0.23 (Revision: 18bbd5e68195d0da083cbd5bd0d05d76320df7cd)
DATE column 1 is expected type java.sql.Date
ERROR: DATETIME column 2 is NOT expected type java.time.LocalDateTime, it is java.sql.Timestamp
TIMESTAMP column 3 is expected type java.sql.Timestamp
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
How to repeat:
import java.sql.*;
public class TimeBug {
private static int executeUpdate(final Connection conn, final String sql) throws SQLException {
try (final Statement st = conn.createStatement()) {
return st.executeUpdate(sql);
}
}
public static void main(final String[] args) throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
try (final Connection conn = DriverManager.getConnection(args[0])) {
final DatabaseMetaData dmd = conn.getMetaData();
System.out.println(dmd.getDriverName() + " version " + dmd.getDriverVersion());
executeUpdate(conn, "DROP TABLE IF EXISTS TimeBug");
executeUpdate(conn, "CREATE TABLE TimeBug (dcol date NOT NULL, dtcol datetime NOT NULL, "
+ "ts timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)");
executeUpdate(conn, "INSERT INTO TimeBug (dcol, dtcol) VALUES (now(), now())");
try (final Statement st = conn.createStatement()) {
final ResultSet rs = st.executeQuery("SELECT * FROM TimeBug");
if (! rs.next()) throw new Error("BUG");
final ResultSetMetaData rsm = rs.getMetaData();
for (int colnum = 1; colnum <= rsm.getColumnCount(); colnum++) {
final Object ob = rs.getObject(colnum);
final String cname = ob.getClass().getName();
final String ctype = rsm.getColumnTypeName(colnum);
final String ccname = rsm.getColumnClassName(colnum);
if (cname.equals(ccname)) {
System.out.println(ctype + " column " + colnum + " is expected type " + cname);
} else {
System.out.println("ERROR: " + ctype + " column " + colnum + " is NOT expected type " + cname
+ ", it is " + ccname);
}
}
}
}
}
}