Bug #117620 NumberFormatException in JDBC
Submitted: 5 Mar 3:20 Modified: 5 Mar 7:50
Reporter: chi zhang Email Updates:
Status: Duplicate Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:9.2.0 OS:Any
Assigned to: CPU Architecture:Any

[5 Mar 3:20] chi zhang
Description:
The following test case triggered a java.lang.NumberFormatException in JDBC driver:
```
DROP DATABASE IF EXISTS database6;
CREATE DATABASE database6;
USE database6;
CREATE TABLE t0(c0 FLOAT ZEROFILL) ;
INSERT INTO t0(c0) VALUES("-0.0");
SELECT t0.c0 FROM t0;
```

When I run it in command line, I get the following outputs:
```
mysql> DROP DATABASE IF EXISTS database6;
Query OK, 1 row affected (0.24 sec)

mysql> CREATE DATABASE database6;
Query OK, 1 row affected (0.07 sec)

mysql> USE database6;
Database changed, 1 warning
mysql> CREATE TABLE t0(c0 FLOAT ZEROFILL) ;
Query OK, 0 rows affected, 1 warning (0.20 sec)

mysql> INSERT INTO t0(c0) VALUES("-0.0");
Query OK, 1 row affected (0.06 sec)

mysql> SELECT t0.c0 FROM t0;
+--------------+
| c0           |
+--------------+
| 0000000000-0 |
+--------------+
1 row in set (0.00 sec)
```

But when I run it with a harness, it triggers an exception. This is the outputs:
```
Connect ...
Connect success.
Query: DROP DATABASE IF EXISTS database6;
Query: CREATE DATABASE database6;
Query: USE database6;
Query: CREATE TABLE t0(c0 FLOAT ZEROFILL) ;
Query: INSERT INTO t0(c0) VALUES("-0.0");
Query: SELECT t0.c0 FROM t0;
For input string: "0000000000-0"
java.lang.NumberFormatException: For input string: "0000000000-0"
        at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
        at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
        at java.base/java.lang.Double.parseDouble(Double.java:543)
        at com.mysql.cj.protocol.a.MysqlTextValueDecoder.getDouble(MysqlTextValueDecoder.java:249)
        at com.mysql.cj.protocol.a.MysqlTextValueDecoder.decodeDouble(MysqlTextValueDecoder.java:134)
        at com.mysql.cj.protocol.a.MysqlTextValueDecoder.decodeFloat(MysqlTextValueDecoder.java:130)
        at com.mysql.cj.protocol.result.AbstractResultsetRow.decodeAndCreateReturnValue(AbstractResultsetRow.java:116)
        at com.mysql.cj.protocol.result.AbstractResultsetRow.getValueFromBytes(AbstractResultsetRow.java:243)
        at com.mysql.cj.protocol.a.result.ByteArrayRow.getValue(ByteArrayRow.java:91)
        at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1334)
        at com.mysql.cj.jdbc.result.ResultSetImpl.getFloat(ResultSetImpl.java:819)
        at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1207)
        at reproduce_mysql$MySQLHandle.batchDate(reproduce_mysql.java:80)
        at reproduce_mysql$MySQLHandle.runSqlByReadFileContent(reproduce_mysql.java:144)
        at reproduce_mysql.main(reproduce_mysql.java:24)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:404)
        at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:179)
        at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:119)
```

How to repeat:
This is the harness:
```
```
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;

import java.text.SimpleDateFormat;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;

public class reproduce_mysql {
    public static void main(String[] args) throws Exception {
        MySQLHandle sh = new MySQLHandle();
        try {
            sh.runSqlByReadFileContent(args[0]);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sh.ReleaseConnect();
        }
    }

    static class MySQLHandle {
        private Connection connection;

        String host = "127.0.0.1";
        int port = 3306;
        String username = "root";
        String password = "123456";
        String url = String.format("jdbc:mysql://%s:%d?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true", host, port);

        public MySQLHandle(){
            try {
                System.out.println("Connect ...");
                connection = DriverManager.getConnection(url, username, password);
                System.out.println("Connect success.");
            } catch (Exception e) {
                e.printStackTrace();
                connection = null;
            }
        }

        public Connection getConnection(){
            return connection;
        }

        public void ReleaseConnect(){
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        public int batchDate(ArrayList<String> sql){
            try (Statement statement = connection.createStatement()){
                for(String script: sql) {
                    if (script.startsWith("--")) {
                        continue;
                    }
                    System.out.println("Query: " + script);
                    if (script.startsWith("SELECT") || script.startsWith("WITH")) {
                        try (ResultSet rs = statement.executeQuery(script)) {
                            ResultSetMetaData metaData = rs.getMetaData();
                            Integer columnCount = metaData.getColumnCount();
                            while (rs.next()) {
                                for (int i = 1; i <= columnCount; i++) {
                                    try {
                                        Object value = rs.getObject(i);
                                    } catch (Exception e) {
                                        System.out.println(e.getMessage());
                                        e.printStackTrace();
                                        System.exit(0);
                                    }
                                }
                            }
                        } catch(Exception e) {
                            System.out.println(e.getMessage());
                            e.printStackTrace();
                            System.exit(0);
                        }
                        
                        
                    } else {
                        try {
                            statement.execute(script);
                        } catch (Exception e) {
                            System.out.println("Error Query: " + script);
                        }
                    }
                }
                return 1;
            }catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }

        private ArrayList<String> readFileByLines(String filePath) throws Exception {
            ArrayList<String> listStr=new ArrayList<>();
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(
                        new FileInputStream(filePath), "UTF-8"));
                String tempString = null;
                while ((tempString = reader.readLine()) != null) {
                    if(tempString.trim().equals(""))
                        continue;
                    if(tempString.startsWith("--"))
                        continue;
                    listStr.add(tempString);
                }
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e1) {
                    }
                }
            }

            return listStr;
        }

        public void runSqlByReadFileContent(String sqlPath){
            try {
                ArrayList<String> sqlStr = readFileByLines(sqlPath);
                if (sqlStr.size() > 0) {
                    int num=batchDate(sqlStr);
                    if(num>0)
                        System.out.println("success!");
                    else
                        System.out.println("failed!");
                }
                else{
                    System.out.println("no sql statements!");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

```
```
I run the MySQL in docker with version `Server version: 9.1.0 MySQL Community Server - GPL`
I use the jdbc driver 8.0.30
I reproduce the exception with the following command:
```
java -cp ~/.m2/repository/mysql/mysql-connector-java/8.0.30/mysql-connector-java-8.0.30.jar ./reproduce_mysql.java database6-reduce.sql
```
[5 Mar 7:44] MySQL Verification Team
Hello chi zhang,

Thank you for the report and test case.
Verified as described.

regards,
Umesh
[5 Mar 7:45] MySQL Verification Team
-- C/J 9.2.0, Server version: 9.2.0 MySQL Community Server - GPL

java -cp mysql-connector-j-9.2.0/mysql-connector-j-9.2.0.jar ./Reproduce_mysql.java database-reduce.sql
Connect ...
Connect success.
Query: CREATE DATABASE database6;
Query: USE database6;
Query: CREATE TABLE t0(c0 FLOAT ZEROFILL) ;
Query: INSERT INTO t0(c0) VALUES("-0.0");
Query: SELECT t0.c0 FROM t0;
For input string: "0000000000-0"
java.lang.NumberFormatException: For input string: "0000000000-0"
	at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
	at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.base/java.lang.Double.parseDouble(Double.java:651)
	at com.mysql.cj.protocol.a.MysqlTextValueDecoder.getDouble(MysqlTextValueDecoder.java:258)
	at com.mysql.cj.protocol.a.MysqlTextValueDecoder.decodeDouble(MysqlTextValueDecoder.java:140)
	at com.mysql.cj.protocol.a.MysqlTextValueDecoder.decodeFloat(MysqlTextValueDecoder.java:135)
	at com.mysql.cj.protocol.result.AbstractResultsetRow.decodeAndCreateReturnValue(AbstractResultsetRow.java:108)
	at com.mysql.cj.protocol.result.AbstractResultsetRow.getValueFromBytes(AbstractResultsetRow.java:235)
	at com.mysql.cj.protocol.a.result.ByteArrayRow.getValue(ByteArrayRow.java:82)
	at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1316)
	at com.mysql.cj.jdbc.result.ResultSetImpl.getFloat(ResultSetImpl.java:841)
	at com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1218)
	at Reproduce_mysql$MySQLHandle.batchDate(Reproduce_mysql.java:79)
	at Reproduce_mysql$MySQLHandle.runSqlByReadFileContent(Reproduce_mysql.java:143)
	at Reproduce_mysql.main(Reproduce_mysql.java:23)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419)
	at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
	at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
[5 Mar 7:50] MySQL Verification Team
IMHO this is duplicate of Bug #114533 JDBC exception java.lang.NumberFormatException, which is marked as won't fix and issue is with the server per developer's last note

[8 Jul 2024 13:01] Filipe Silva
Not a bug in MySQL Connector/J. Related to MySQL Server Bug#115493.

Bug#115493 is private hence not visible at the moment.