Skip to content

Commit 662c0df

Browse files
committed
Reject DecimalType with precision larger than 38
The Iceberg spec requires decimal precision to be 38 or less, but DecimalType(39, 0) (and parsing 'decimal(39, 0)') was accepted silently, producing a value not representable in decimal's fixed-byte storage. Validate precision <= 38 in DecimalType.__init__, matching the Java reference which raises for precision > 38. Closes #3583
1 parent 9d36e23 commit 662c0df

2 files changed

Lines changed: 11 additions & 0 deletions

File tree

pyiceberg/types.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ class DecimalType(PrimitiveType):
324324
root: tuple[int, int]
325325

326326
def __init__(self, precision: int, scale: int) -> None:
327+
if precision > 38:
328+
raise ValueError(f"Decimals with precision larger than 38 are not supported: {precision}")
327329
super().__init__(root=(precision, scale))
328330

329331
@model_serializer

tests/test_types.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,15 @@ def test_decimal_type() -> None:
147147
assert type_var == pickle.loads(pickle.dumps(type_var))
148148

149149

150+
def test_decimal_type_rejects_precision_over_38() -> None:
151+
# The Iceberg spec requires decimal precision to be 38 or less; the Java
152+
# reference implementation raises for precision > 38. See issue #3583.
153+
with pytest.raises(ValueError, match="precision larger than 38 are not supported: 39"):
154+
DecimalType(39, 0)
155+
# Boundary: precision exactly 38 is still valid.
156+
assert DecimalType(38, 0).precision == 38
157+
158+
150159
def test_struct_type() -> None:
151160
type_var = StructType(
152161
NestedField(1, "optional_field", IntegerType(), required=True),

0 commit comments

Comments
 (0)