Bug #18880 Resultset.getFloatFromString does not work for Float min or max value
Submitted: 7 Apr 2006 9:02 Modified: 26 Jul 2006 18:17
Reporter: Stephane Giron Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S2 (Serious)
Version:3.1.12 OS:Linux (Linux Ubuntu)
Assigned to: CPU Architecture:Any

[7 Apr 2006 9:02] Stephane Giron
Description:
Double.parseDouble(string) and Float.parseFloat(String) may give different results for a same string, as shown in this example :

    String strMin = Float.toString(Float.MIN_VALUE);
    String strMax = Float.toString(Float.MAX_VALUE);
    
    System.out.println(Float.parseFloat(strMin) == Double.parseDouble(strMin));
    System.out.println(Float.parseFloat(strMax) == Double.parseDouble(strMax));

The result of this for me is :
false
false

This simple example is equivalent to what is done is Resultset.getFloatFromString, which is called when using CallableStatement.getFloat().

How to repeat:
      stmt = conn.createStatement();
      stmt
          .executeUpdate("create table Real_Tab (MAX_VAL REAL, MIN_VAL REAL,NULL_VAL REAL NULL) ");
      stmt.executeUpdate("drop procedure if exists Real_Proc");
      stmt.executeUpdate("create procedure Real_Proc (OUT MAX_PARAM REAL, OUT MIN_PARAM REAL, OUT NULL_PARAM REAL) select MAX_VAL, MIN_VAL, NULL_VAL  into MAX_PARAM, MIN_PARAM, NULL_PARAM from Real_Tab;");
      stmt.executeUpdate("insert into Real_Tab values(3.4E38,1.4E-45, null)");

      cstmt = conn.prepareCall("{call Real_Proc(?,?,?)}");

      cstmt.registerOutParameter(1, java.sql.Types.REAL);
      cstmt.registerOutParameter(2, java.sql.Types.REAL);
      cstmt.registerOutParameter(3, java.sql.Types.REAL);

      cstmt.execute();
      float fRetVal = cstmt.getFloat(2);

Suggested fix:
Simple fix is to take account of the precision loss, as shown below.

        if (this.connection.getJdbcCompliantTruncation())
        {
          if (f == Float.MIN_VALUE || f == Float.MAX_VALUE)
          {
            double valAsDouble = Double.parseDouble(val);

            // Get the string representations of float min and max values
            String strMin = Float.toString(Float.MIN_VALUE);
            String strMax = Float.toString(Float.MAX_VALUE);

            // Check if there is a difference of precision between float and
            // double representation of those strings
            double minDiffPrec = Float.parseFloat(strMin)
                - Double.parseDouble(strMin);
            double maxDiffPrec = Float.parseFloat(strMax)
                - Double.parseDouble(strMax);

            // Now take into accounts these potential differences
            if ((valAsDouble < Float.MIN_VALUE - minDiffPrec)
                || (valAsDouble > Float.MAX_VALUE - maxDiffPrec))
            {
              throwRangeException(String.valueOf(valAsDouble), columnIndex,
                  Types.FLOAT);
            }
          }
        }
[26 May 2006 9:01] Tonci Grgin
Hi Stephane. Thanks for your problem report and your input on this.
Verified as described by user.
[18 Jul 2006 18:01] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/9289