Skip to content

Commit b231705

Browse files
abnobdossAbanoub Doss
andauthored
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 <abanoub.doss@gmail.com>
1 parent 835e13a commit b231705

2 files changed

Lines changed: 11 additions & 2 deletions

File tree

pyiceberg/expressions/literals.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,9 +526,9 @@ def _(self, _: IntegerType) -> Literal[int]:
526526
def _(self, _: LongType) -> Literal[int]:
527527
value_int = int(self.value.to_integral_value())
528528
if value_int > LongType.max:
529-
return IntAboveMax()
529+
return LongAboveMax()
530530
elif value_int < LongType.min:
531-
return IntBelowMin()
531+
return LongBelowMin()
532532
else:
533533
return LongLiteral(value_int)
534534

tests/expressions/test_literals.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
IntBelowMin,
4141
Literal,
4242
LongAboveMax,
43+
LongBelowMin,
4344
LongLiteral,
4445
StringLiteral,
4546
TimeLiteral,
@@ -878,6 +879,14 @@ def test_string_to_long_large_scientific_notation_above_max() -> None:
878879
assert isinstance(literal("1e1000000").to(LongType()), LongAboveMax)
879880

880881

882+
def test_decimal_to_long_above_max() -> None:
883+
assert isinstance(DecimalLiteral(Decimal(LongType.max + 1)).to(LongType()), LongAboveMax)
884+
885+
886+
def test_decimal_to_long_below_min() -> None:
887+
assert isinstance(DecimalLiteral(Decimal(LongType.min - 1)).to(LongType()), LongBelowMin)
888+
889+
881890
def test_string_to_integer_type_invalid_value() -> None:
882891
with pytest.raises(ValueError) as e:
883892
_ = literal("abc").to(IntegerType())

0 commit comments

Comments
 (0)