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())