diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a5e33347..543001c0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Release History # Unreleased +- Correct explicit `DecimalParameter` precision and scale ordering and honor a declared zero scale. Callers that followed the previously reversed parameter descriptions must use `precision` for total digits and `scale` for fractional digits. Explicit zero precision is now sent as declared instead of silently using automatic sizing. - Add the `escape_catalog_name` connection parameter (default `False`) to opt in to escaping unescaped `_` in metadata catalog names on Thrift and kernel connections. Existing escapes and `%` wildcards are preserved. # 4.6.0 (2026-09-24) diff --git a/src/databricks/sql/parameters/native.py b/src/databricks/sql/parameters/native.py index d0d811940..01339cdac 100644 --- a/src/databricks/sql/parameters/native.py +++ b/src/databricks/sql/parameters/native.py @@ -615,9 +615,9 @@ def __init__( The `name` argument to this function would be `my_param`. :scale: - The maximum precision (total number of digits) of the number between 1 and 38. + The number of digits to the right of the decimal point, from 0 to precision. :precision: - The number of digits to the right of the decimal point. + The maximum precision (total number of digits) of the number between 1 and 38. """ self.value: decimal.Decimal = value self.name = name @@ -638,8 +638,8 @@ def valid_scale_and_precision(self): return False def _cast_expr(self): - if self.scale and self.precision: - return self.CAST_EXPR.format(self.scale, self.precision) + if self.scale is not None and self.precision is not None: + return self.CAST_EXPR.format(self.precision, self.scale) else: return self.calculate_decimal_cast_string(self.value) diff --git a/tests/unit/test_parameters.py b/tests/unit/test_parameters.py index 0588eb499..66b0e48e9 100644 --- a/tests/unit/test_parameters.py +++ b/tests/unit/test_parameters.py @@ -107,6 +107,21 @@ def test_calculate_decimal_cast_string(value, expected): assert p._cast_expr() == expected +@pytest.mark.parametrize( + "value,precision,scale,expected", + ( + (Decimal("123.45"), 10, 2, "DECIMAL(10,2)"), + (Decimal("123"), 10, 0, "DECIMAL(10,0)"), + (Decimal("123.45"), None, None, "DECIMAL(5,2)"), + ), +) +def test_decimal_parameter_explicit_type(value, precision, scale, expected): + parameter = DecimalParameter(value, precision=precision, scale=scale) + bound = parameter.as_tspark_param(named=False) + assert bound.type == expected + assert bound.value.stringValue == str(value) + + class Primitive(Enum): """These are the inferrable types. This Enum is used for parametrized tests."""