scruz-denodo opened a new issue, #1406:
URL: https://github.com/apache/arrow-java/issues/1406
### Describe the bug, including details regarding any error messages,
version, and platform.
## Describe the bug
ArrowFlightJdbcFloat4VectorAccessor widens the underlying float to double
directly. Reading a Float4Vector (SQL REAL/FLOAT4) through
`ResultSet.getDouble()`, `ResultSet.getBigDecimal()` or
`ResultSet.getObject(col, Double.class)` therefore returns the binary
approximation of the float, not the decimal value the float stands for.
- `getDouble()` is implemented as `(double) getFloat()`.
- `getBigDecimal()` and `getBigDecimal(int scale)` use
`BigDecimal.valueOf(float)`, which widens to double first.
- `getObject(Double.class)` goes through `getDouble()` in
`ArrowFlightJdbcAccessor.getObject(Class)`.
- `getString()` already uses Float.toString(value), so the same cell gives
different results depending on the getter:
**Result for a 0.1f cell**
- getString(): "0.1"
- getDouble(): 0.10000000149011612
- getBigDecimal(): 0.10000000149011612
**To Reproduce**
``` java
try (Float4Vector v = new Float4Vector("f", allocator)) {
v.setSafe(0, 0.1f);
v.setValueCount(1);
ArrowFlightJdbcFloat4VectorAccessor acc =
new ArrowFlightJdbcFloat4VectorAccessor(v, () -> 0, (wasNull) -> {});
acc.getString(); // "0.1"
acc.getDouble(); // 0.10000000149011612 (expected 0.1)
acc.getBigDecimal(); // 0.10000000149011612 (expected 0.1)
}
```
The same happens through a real connection with a query returning a REAL
column containing `0.1`, `1.1`, `123.456` and similar values.
**Expected behaviour**
For a finite `float`, `getDouble()`, `getBigDecimal()` and
`getObject(Double.class)` should return the decimal value the float represents.
That is the shortest decimal that uniquely identifies the float, the same one
`Float.toString` yields. For `0.1f` that is `0.1`, which is what `getString()`
already returns. Other JDBC drivers show this behaviour for REAL columns.
**Proposed fix**
``` java
Convert through the float's decimal representation:
public double getDouble() {
return Double.parseDouble(Float.toString(this.getFloat()));
}
public BigDecimal getBigDecimal() throws SQLException {
final float value = this.getFloat();
if (Float.isInfinite(value) || Float.isNaN(value)) {
throw new SQLException("BigDecimal doesn't support Infinite/NaN.");
}
return this.wasNull ? null : new BigDecimal(Float.toString(value));
}
```
`getBigDecimal(int scale)` gets the same change, followed by
`.setScale(scale, RoundingMode.HALF_UP)`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]