You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by fo...@apache.org on 2026/06/09 18:28:25 UTC

(iceberg-python) branch main updated: fix(literals): Return Long bounds for Decimal conversion (#3470)

This is an automated email from the ASF dual-hosted git repository.

Fokko pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-python.git


The following commit(s) were added to refs/heads/main by this push:
     new b23170597 fix(literals): Return Long bounds for Decimal conversion (#3470)
b23170597 is described below

commit b231705972ab1d78a39d8758a3ae32444d3e5549
Author: abnobdoss <ab...@gmail.com>
AuthorDate: Tue Jun 9 13:28:19 2026 -0500

    fix(literals): Return Long bounds for Decimal conversion (#3470)
    
    Closes #3469
    
    # Rationale for this change
    
    Decimal literals converted to `LongType` should use long bound sentinels
    when the value is outside the long range. The existing conversion
    returned integer sentinels, mismatching the requested target type.
    
    This returns `LongAboveMax` and `LongBelowMin` for decimal-to-long
    overflow.
    
    ### Relationship to Java
    
    Java's `DecimalLiteral.to(...)` only handles `DECIMAL` and returns
    `null` for other target types
    ([`Literals.java#L497-L505`](https://github.com/apache/iceberg/blob/main/api/src/main/java/org/apache/iceberg/expressions/Literals.java#L497-L505)),
    so there is no direct decimal-to-long branch to mirror. This keeps
    PyIceberg's long conversion consistent with its typed integer overflow
    handling. Java's generic valueless overflow sentinels are a broader
    semantic difference and are out of scope here.
    
    ## Are these changes tested?
    
    Yes. New literal tests cover decimal values above and below the
    `LongType` range.
    
    ## Are there any user-facing changes?
    
    Yes. Decimal literal conversion to `LongType` now reports overflow with
    the correct long sentinel type.
    
    Co-authored-by: Abanoub Doss <ab...@gmail.com>
---
 pyiceberg/expressions/literals.py  | 4 ++--
 tests/expressions/test_literals.py | 9 +++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/pyiceberg/expressions/literals.py b/pyiceberg/expressions/literals.py
index 50c6d2d61..1ff800852 100644
--- a/pyiceberg/expressions/literals.py
+++ b/pyiceberg/expressions/literals.py
@@ -526,9 +526,9 @@ class DecimalLiteral(Literal[Decimal]):
     def _(self, _: LongType) -> Literal[int]:
         value_int = int(self.value.to_integral_value())
         if value_int > LongType.max:
-            return IntAboveMax()
+            return LongAboveMax()
         elif value_int < LongType.min:
-            return IntBelowMin()
+            return LongBelowMin()
         else:
             return LongLiteral(value_int)
 
diff --git a/tests/expressions/test_literals.py b/tests/expressions/test_literals.py
index b37c94762..de9d39077 100644
--- a/tests/expressions/test_literals.py
+++ b/tests/expressions/test_literals.py
@@ -40,6 +40,7 @@ from pyiceberg.expressions.literals import (
     IntBelowMin,
     Literal,
     LongAboveMax,
+    LongBelowMin,
     LongLiteral,
     StringLiteral,
     TimeLiteral,
@@ -878,6 +879,14 @@ def test_string_to_long_large_scientific_notation_above_max() -> None:
     assert isinstance(literal("1e1000000").to(LongType()), LongAboveMax)
 
 
+def test_decimal_to_long_above_max() -> None:
+    assert isinstance(DecimalLiteral(Decimal(LongType.max + 1)).to(LongType()), LongAboveMax)
+
+
+def test_decimal_to_long_below_min() -> None:
+    assert isinstance(DecimalLiteral(Decimal(LongType.min - 1)).to(LongType()), LongBelowMin)
+
+
 def test_string_to_integer_type_invalid_value() -> None:
     with pytest.raises(ValueError) as e:
         _ = literal("abc").to(IntegerType())