diff --git a/pyiceberg/schema.py b/pyiceberg/schema.py index fd60eb8f94..a79b3ae95f 100644 --- a/pyiceberg/schema.py +++ b/pyiceberg/schema.py @@ -1697,7 +1697,7 @@ def _(file_type: BinaryType, read_type: IcebergType) -> IcebergType: @promote.register(DecimalType) def _(file_type: DecimalType, read_type: IcebergType) -> IcebergType: if isinstance(read_type, DecimalType): - if file_type.precision <= read_type.precision and file_type.scale == file_type.scale: + if file_type.precision <= read_type.precision and file_type.scale == read_type.scale: return read_type else: raise ResolveError(f"Cannot reduce precision from {file_type} to {read_type}") diff --git a/tests/test_schema.py b/tests/test_schema.py index 93ddc16202..e9282c0f87 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -68,6 +68,7 @@ DoubleType(), DecimalType(10, 2), DecimalType(100, 2), + DecimalType(10, 3), StringType(), DateType(), TimeType(), @@ -878,7 +879,7 @@ def should_promote(file_type: IcebergType, read_type: IcebergType) -> bool: if isinstance(file_type, BinaryType) and isinstance(read_type, StringType): return True if isinstance(file_type, DecimalType) and isinstance(read_type, DecimalType): - return file_type.precision <= read_type.precision and file_type.scale == file_type.scale + return file_type.precision <= read_type.precision and file_type.scale == read_type.scale if isinstance(file_type, FixedType) and isinstance(read_type, UUIDType) and len(file_type) == 16: return True return False @@ -1316,6 +1317,15 @@ def test_type_promote_decimal_to_fixed_scale_with_wider_precision(table_v2: Tabl assert decimal_type.scale == 1 +def test_detect_invalid_promotion_decimal_scale_change(table_v2: Table) -> None: + # Per the Iceberg spec, decimal scale is fixed; only precision may grow. + current_schema = Schema(NestedField(field_id=1, name="aCol", field_type=DecimalType(precision=20, scale=1), required=False)) + new_schema = Schema(NestedField(field_id=1, name="aCol", field_type=DecimalType(precision=22, scale=2), required=False)) + + with pytest.raises(ValidationError, match="Cannot change column type: aCol: decimal.20, 1. -> decimal.22, 2."): + _ = UpdateSchema(transaction=Transaction(table_v2), schema=current_schema).union_by_name(new_schema)._apply() + + def test_add_nested_structs(primitive_fields: NestedField, table_v2: Table) -> None: schema = Schema( NestedField(