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]

Reply via email to