diff --git a/pyiceberg/types.py b/pyiceberg/types.py index 3c98215366..b0e5d204b0 100644 --- a/pyiceberg/types.py +++ b/pyiceberg/types.py @@ -324,6 +324,8 @@ class DecimalType(PrimitiveType): root: tuple[int, int] def __init__(self, precision: int, scale: int) -> None: + if precision > 38: + raise ValueError(f"Decimals with precision larger than 38 are not supported: {precision}") super().__init__(root=(precision, scale)) @model_serializer diff --git a/tests/test_schema.py b/tests/test_schema.py index 93ddc16202..aacdbc7d5e 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -67,7 +67,7 @@ FloatType(), DoubleType(), DecimalType(10, 2), - DecimalType(100, 2), + DecimalType(38, 2), StringType(), DateType(), TimeType(), diff --git a/tests/test_types.py b/tests/test_types.py index 5e95687ba2..d6e5a682b5 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -147,6 +147,15 @@ def test_decimal_type() -> None: assert type_var == pickle.loads(pickle.dumps(type_var)) +def test_decimal_type_rejects_precision_over_38() -> None: + # The Iceberg spec requires decimal precision to be 38 or less; the Java + # reference implementation raises for precision > 38. See issue #3583. + with pytest.raises(ValueError, match="precision larger than 38 are not supported: 39"): + DecimalType(39, 0) + # Boundary: precision exactly 38 is still valid. + assert DecimalType(38, 0).precision == 38 + + def test_struct_type() -> None: type_var = StructType( NestedField(1, "optional_field", IntegerType(), required=True),