zeroshade opened a new issue, #2092:
URL: https://github.com/apache/iceberg-go/issues/2092
**Problem**
`DecimalLiteral.To` converts to `Int32Type`/`Int64Type` from the unscaled
value (`d.Val.BigInt()`, literals.go:1346 and :1363 on main) and ignores
`Scale`, so 12.34 (`Decimal{Val: 1234, Scale: 2}`) becomes 1234. The float
branches of the same method do apply the scale (literals.go:1373-1383), so one
literal converts to int 1234 and to float 12.34.
`TestDecimalLiteralConversions` pins both (literals_test.go:491-495; the `n3`
row at :496 does the same with scale 10).
Binding a decimal literal against an int/long column therefore filters on
the wrong value. With #2088, `VariantLiteral.To` delegates to the literal for
the variant's value, so variant decimals bound to int columns hit this as well.
**Reproduction**
```go
d := iceberg.Decimal{Val: decimal128.FromI64(1234), Scale: 2} // 12.34
lit := iceberg.NewLiteral(d)
lit.To(iceberg.PrimitiveTypes.Int32)
lit.To(iceberg.PrimitiveTypes.Int64)
lit.To(iceberg.PrimitiveTypes.Float32)
sc := iceberg.NewSchema(1, iceberg.NestedField{ID: 1, Name: "qty", Type:
iceberg.PrimitiveTypes.Int32})
iceberg.BindExpr(sc, iceberg.EqualTo(iceberg.Reference("qty"), d), true)
```
On main (dd935d8):
```
DecimalLiteral(12.34).To(int) = 1234
DecimalLiteral(12.34).To(long) = 1234
DecimalLiteral(12.34).To(float) = 12.34
BindExpr(qty == 12.34) = BoundEqual(term=BoundReference(field=1: qty:
optional int, accessor=Accessor(position=0, inner=<nil>)), literal=1234)
```
Expected: the int/long casts don't produce 1234, so `qty == 12.34` can't
match rows where `qty = 1234`.
**Other implementations**
- Java: `Literals.DecimalLiteral.to` only accepts `DECIMAL`; every other
target returns null (no conversion).
- pyiceberg: `DecimalLiteral.to(IntegerType/LongType)` rounds with
`Decimal.to_integral_value()`, so 12.34 becomes 12.
**Proposed fix**
Match Java: return `ErrBadCast` for `Int32Type`/`Int64Type`, and update the
pinned rows and the decimal-to-int AboveMax/BelowMin assertions in
`TestDecimalLiteralConversions`. If we'd rather keep exact conversions, rescale
to 0 and fail when digits are lost (12.00 -> 12, 12.34 -> error). Rounding like
pyiceberg isn't safe for range predicates: `qty < 12.34` would bind as `qty <
12`.
**Related**
- #2088: `VariantLiteral.To` delegation makes variant decimals reach this
path
- #1322 / #1323: overflow-direction fix in the same branches
--
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]