Skip to content
Permalink
Browse files

fix: return Double.NaN for 'NaN'::numeric (#1304)

'NaN'::real => Float.NaN
'NaN'::double precision => Double.NaN
'NaN'::numeric => Double.NaN
  • Loading branch information...
tseylerd authored and vlsi committed Sep 21, 2018
1 parent b53eedf commit 265f22b28fd7b5511e30a28ad959d5645e9722cd
@@ -188,10 +188,16 @@ public String toString(int index, boolean standardConformingStrings) {

case Oid.FLOAT4:
float f = ByteConverter.float4((byte[]) paramValues[index], 0);
if (Float.isNaN(f)) {
return "'NaN'::real";
}
return Float.toString(f);

case Oid.FLOAT8:
double d = ByteConverter.float8((byte[]) paramValues[index], 0);
if (Double.isNaN(d)) {
return "'NaN'::double precision";
}
return Double.toString(d);

case Oid.UUID:
@@ -185,8 +185,8 @@ protected Object internalGetObject(int columnIndex, Field field) throws SQLExcep
return getLong(columnIndex);
case Types.NUMERIC:
case Types.DECIMAL:
return getBigDecimal(columnIndex,
(field.getMod() == -1) ? -1 : ((field.getMod() - 4) & 0xffff));
return getNumeric(columnIndex,
(field.getMod() == -1) ? -1 : ((field.getMod() - 4) & 0xffff), true);
case Types.REAL:
return getFloat(columnIndex);
case Types.FLOAT:
@@ -2325,6 +2325,10 @@ public double getDouble(int columnIndex) throws SQLException {

public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
connection.getLogger().log(Level.FINEST, " getBigDecimal columnIndex: {0}", columnIndex);
return (BigDecimal) getNumeric(columnIndex, scale, false);
}

private Number getNumeric(int columnIndex, int scale, boolean allowNaN) throws SQLException {
checkResultSet(columnIndex);
if (wasNullFlag) {
return null;
@@ -2352,11 +2356,15 @@ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException
BigDecimal res = getFastBigDecimal(columnIndex);
res = scaleBigDecimal(res, scale);
return res;
} catch (NumberFormatException ex) {
} catch (NumberFormatException ignore) {
}
}

return toBigDecimal(getFixedString(columnIndex), scale);
String stringValue = getFixedString(columnIndex);
if (allowNaN && "NaN".equalsIgnoreCase(stringValue)) {
return Double.NaN;
}
return toBigDecimal(stringValue, scale);
}

/**
@@ -568,6 +568,62 @@ public void testFloat() throws SQLException {

}

@Test
public void testNaNLiteralsSimpleStatement() throws SQLException {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'NaN'::numeric, 'NaN'::real, 'NaN'::double precision");
checkNaNLiterals(stmt, rs);
}

@Test
public void testNaNLiteralsPreparedStatement() throws SQLException {
PreparedStatement stmt = con.prepareStatement("select 'NaN'::numeric, 'NaN'::real, 'NaN'::double precision");
checkNaNLiterals(stmt, stmt.executeQuery());
}

private void checkNaNLiterals(Statement stmt, ResultSet rs) throws SQLException {
rs.next();
assertTrue("Double.isNaN((Double) rs.getObject", Double.isNaN((Double) rs.getObject(3)));
assertTrue("Double.isNaN(rs.getDouble", Double.isNaN(rs.getDouble(3)));
assertTrue("Float.isNaN((Float) rs.getObject", Float.isNaN((Float) rs.getObject(2)));
assertTrue("Float.isNaN(rs.getFloat", Float.isNaN(rs.getFloat(2)));
assertTrue("Double.isNaN((Double) rs.getObject", Double.isNaN((Double) rs.getObject(1)));
assertTrue("Double.isNaN(rs.getDouble", Double.isNaN(rs.getDouble(1)));
rs.close();
stmt.close();
}

@Test
public void testNaNSetDoubleFloat() throws SQLException {
PreparedStatement ps = con.prepareStatement("select ?, ?");
ps.setFloat(1, Float.NaN);
ps.setDouble(2, Double.NaN);

checkNaNParams(ps);
}

@Test
public void testNaNSetObject() throws SQLException {
PreparedStatement ps = con.prepareStatement("select ?, ?");
ps.setObject(1, Float.NaN);
ps.setObject(2, Double.NaN);

checkNaNParams(ps);
}

private void checkNaNParams(PreparedStatement ps) throws SQLException {
ResultSet rs = ps.executeQuery();
rs.next();

assertTrue("Float.isNaN((Float) rs.getObject", Float.isNaN((Float) rs.getObject(1)));
assertTrue("Float.isNaN(rs.getFloat", Float.isNaN(rs.getFloat(1)));
assertTrue("Double.isNaN(rs.getDouble", Double.isNaN(rs.getDouble(2)));
assertTrue("Double.isNaN(rs.getDouble", Double.isNaN(rs.getDouble(2)));

TestUtil.closeQuietly(rs);
TestUtil.closeQuietly(ps);
}

@Test
public void testBoolean() throws SQLException {
testBoolean(0);

0 comments on commit 265f22b

Please sign in to comment.
You can’t perform that action at this time.