awslabs / aws-mysql-jdbc

The Amazon Web Services (AWS) JDBC Driver for MySQL is a driver that enables applications to take full advantage of the features of clustered MySQL databases.
https://awslabs.github.io/aws-mysql-jdbc/
Other
226 stars 49 forks source link

Wrong Exception thrown for ResultSet getters when there are incompatible data types #315

Closed buitcj closed 1 year ago

buitcj commented 1 year ago

Describe the bug

As the docs say the aurora mysql driver can be used as a drop-in compatible for the MySQL Connector/J driver, it might be expected that the aws mysql driver behaves as the mysql one. Calling ResultSet#getInt on a varchar column will cause a java.lang.NumberFormatException (e.g., java.lang.NumberFormatException: For input string: "hello world") in the aws mysql driver but in the MySQL driver it will cause a java.sql.SQLException (e.g., java.sql.SQLException: Invalid value for getInt() - 'hello world').

Expected Behavior

java.sql.SQLException is thrown

Current Behavior

java.lang.NumberFormatException is thrown

Reproduction Steps

Create a table with a varchar column and insert a row, for example: CREATE TABLE TT (val varchar(255)); INSERT INTO TT VALUES ('hello world');

Put both the MySQL and AWS MySQL drivers on the classpath and use the following code.

    software.aws.rds.jdbc.mysql.Driver.setAcceptAwsProtocolOnly(true);

    try (
        Connection conn = DriverManager.getConnection(jdbcUrl, userName, password);
        Statement statement = conn.createStatement();
        ResultSet resultSet = statement.executeQuery("SELECT * FROM TT;");
    ) {
      while (resultSet.next()) {
        int firstVal = resultSet.getInt(1);
      }
    }

Using an AWS Aurora MySQL instance, use a mysql style jdbc URL to see the SQLException (e.g., jdbc:mysql://...) and use an aurora mysql style jdbc URL to see the NumberFormatException (e.g., jdbc:mysql:aws://...)

Possible Solution

Wrap the ResultSetImpl#get- methods with the wrapper code that some of the methods already have to make it consistent:

} catch (NumberFormatException nfe) {
            throw SQLError.createSQLException(

Additional Information/Context

No response

The AWS JDBC Driver for MySQL version used

1.1.1

JDK version used

1.8

Operating System and version

MacOS Monterey 12.6.1

buitcj commented 1 year ago

I recognize this is probably a really minor thing that the maintainers might not decide to fix but I wanted to at least bring it up for discussion and visibility.

alecc-bq commented 1 year ago

Hello @buitcj,

Thank you for raising this issue. I am having some troubles reproducing this bug, would you be able to specify the MySQL driver version you are using?

buitcj commented 1 year ago

@alecc-bq Sorry my repro steps needed to be refined a bit. I edited/simplified the code (before it was needlessly wrapping the exception) and also made sure to provide a row in the table which is crucial because a value like asdf won't cause a problem but a value like hello world or hello-world will. Please take another look at the repro when you get a chance.

FYI: I am using mysql-connector-java:5.1.49, but the version is not the reason why you were not able to reproduce it.

alecc-bq commented 1 year ago

Hello @buitcj,

After reviewing changes in the reproduction steps on the issue, I still am having difficulties replicating this bug. I am getting the same Exception in thread "main" java.lang.NumberFormatException: For input string: "hello world" with both AWS MySQL driver, and the regular MySQL driver. For reference, here is a snippet of my sample code:

    public static void main(String[] args) throws SQLException {

        software.aws.rds.jdbc.mysql.Driver.setAcceptAwsProtocolOnly(true);

        try (
            Connection conn = DriverManager.getConnection(CONNECTION_STRING, USERNAME, PASSWORD);
            Statement statement = conn.createStatement();
            ResultSet resultSet = statement.executeQuery("SELECT * FROM temp.TT;");
        ) {
            while (resultSet.next()) {
                int firstVal = resultSet.getInt(1);
            }
        }
    }

I am replacing the connection string constant depending on whether I am using AWS or regular MySQL driver.

Thank you

buitcj commented 1 year ago

@alecc-bq hmm I don't know. The problem is very reproducible on my side now since I modified the repro steps. Just to make sure, when you are using the mysql driver, you are still executing against the aurora mysql instance right? and using "jdbc:mysql://..." format? can you debug the call to make sure it's going into the mysql driver?

alecc-bq commented 1 year ago

Hello @buitcj, yes I am executing against the same Aurora MySQL instance. For reference, this is what my connection strings look like: "jdbc:mysql://db-identifier.XYZ.us-east-2.rds.amazonaws.com" and "jdbc:mysql:aws://db-identifier.XYZ.us-east-2.rds.amazonaws.com". I used the debugger and confirmed that it is going into the MySQL driver when using the first connection string.

UPDATE: Tried downgrading the MySQL driver version to 5.1.49 and was able to reproduce this bug. Seems like updating the driver version should take care of it.

Thank you!

buitcj commented 1 year ago

@alecc-bq thanks for looking into this. I will close this out now.

I am working around the difference in behaviors since I am not able to upgrade at this time.