Skip to content

Commit 1e6d743

Browse files
[SPARK-54750][SQL] Fix ROUND returning NULL for Decimal values with l…
### What changes were proposed in this pull request? Fixed a bug in `RoundBase` where `ROUND` function incorrectly returns `NULL` for certain Decimal values. The issue was caused by using the input decimal's runtime precision instead of the target type's precision when calling `toPrecision()`. For example, `ROUND(PERCENTILE_APPROX(2150 / 1000.0, 0.95), 3)` incorrectly returned `NULL` instead of `2.15`. ### Why are the changes needed? The fix changes `decimal.toPrecision(decimal.precision, s, mode)` to `decimal.toPrecision(p, s, mode)` in both `nullSafeEval` and `doGenCode` methods, where `p` is the target DecimalType's precision. ### Does this PR introduce _any_ user-facing change? Yes, this fixes a bug where ROUND could return NULL for valid decimal inputs. ### How was this patch tested? Added regression test in `ApproximatePercentileQuerySuite`. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #53529 from qindongliang/SPARK-54750-fix-round-precision. Lead-authored-by: qindongliang <[email protected]> Co-authored-by: Kent Yao <[email protected]> Signed-off-by: Kent Yao <[email protected]>
1 parent 0da9e05 commit 1e6d743

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/mathExpressions.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,7 +1572,7 @@ abstract class RoundBase(child: Expression, scale: Expression,
15721572
val decimal = input1.asInstanceOf[Decimal]
15731573
if (_scale >= 0) {
15741574
// Overflow cannot happen, so no need to control nullOnOverflow
1575-
decimal.toPrecision(decimal.precision, s, mode)
1575+
decimal.toPrecision(p, s, mode)
15761576
} else {
15771577
Decimal(decimal.toBigDecimal.setScale(_scale, mode), p, s)
15781578
}
@@ -1644,10 +1644,9 @@ abstract class RoundBase(child: Expression, scale: Expression,
16441644
case DecimalType.Fixed(p, s) =>
16451645
if (_scale >= 0) {
16461646
s"""
1647-
${ev.value} = ${ce.value}.toPrecision(${ce.value}.precision(), $s,
1648-
Decimal.$modeStr(), true, null);
1647+
${ev.value} = ${ce.value}.toPrecision($p, $s, Decimal.$modeStr(), true, null);
16491648
${ev.isNull} = ${ev.value} == null;"""
1650-
} else {
1649+
} else {
16511650
s"""
16521651
${ev.value} = new Decimal().set(${ce.value}.toBigDecimal()
16531652
.setScale(${_scale}, Decimal.$modeStr()), $p, $s);

sql/core/src/test/scala/org/apache/spark/sql/ApproximatePercentileQuerySuite.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,4 +370,16 @@ class ApproximatePercentileQuerySuite extends QueryTest with SharedSparkSession
370370
context = ExpectedContext(
371371
"", "", 8, 40, "percentile_approx(col, NULL, 100)"))
372372
}
373+
374+
test("SPARK-54750: percentile_approx returns NULL for certain decimal values") {
375+
// Regression test: ROUND(PERCENTILE_APPROX(2150/1000.0, 0.95), 3) should return 2.15
376+
checkAnswer(
377+
spark.sql("SELECT ROUND(PERCENTILE_APPROX(2150 / 1000.0, 0.95), 3) as p95"),
378+
Row(2.15)
379+
)
380+
checkAnswer(
381+
spark.sql("SELECT ROUND(PERCENTILE_APPROX(2151 / 1000.0, 0.95), 3) as p95"),
382+
Row(2.151)
383+
)
384+
}
373385
}

0 commit comments

Comments
 (0)