Bug #102321 Calling ResultSetMetaData.getColumnClassName returns wrong value for DATETIME
Submitted: 20 Jan 2021 19:27 Modified: 5 Mar 2021 22:48
Reporter: Andre Burgoyne Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:8.0.23 OS:Any
Assigned to: CPU Architecture:Any

[20 Jan 2021 19:27] Andre Burgoyne
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);
                    }
                }
            }
        }
    }
}
[21 Jan 2021 5:47] MySQL Verification Team
Hello Andre,

Thank you for the report and test case.

regards,
Umesh
[5 Mar 2021 22:48] Daniel So
Posted by developer:
 
Added the following entry to the Connector/J 8.0.24 changelog: 

"When using Connector/J 8,.0.23, ResultSetMetaData.getColumnClassName() did not return the correct class name corresponding to DATETIME columns."