This is an automated email from the ASF dual-hosted git repository.

yao pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 94431221bbf2 [SPARK-54750][SQL] Fix ROUND returning NULL for Decimal 
values with l…
94431221bbf2 is described below

commit 94431221bbf2a951be6bdf6769eb14015f287bf2
Author: qindongliang <[email protected]>
AuthorDate: Sat Dec 20 00:39:51 2025 +0800

    [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]>
    (cherry picked from commit 1e6d743c7ae235b3a23700d9cfdf924cb5e25d61)
    Signed-off-by: Kent Yao <[email protected]>
---
 .../spark/sql/catalyst/expressions/mathExpressions.scala     |  7 +++----
 .../apache/spark/sql/ApproximatePercentileQuerySuite.scala   | 12 ++++++++++++
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/mathExpressions.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/mathExpressions.scala
index ee3e3e027276..0643e5fba2f3 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/mathExpressions.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/mathExpressions.scala
@@ -1572,7 +1572,7 @@ abstract class RoundBase(child: Expression, scale: 
Expression,
         val decimal = input1.asInstanceOf[Decimal]
         if (_scale >= 0) {
           // Overflow cannot happen, so no need to control nullOnOverflow
-          decimal.toPrecision(decimal.precision, s, mode)
+          decimal.toPrecision(p, s, mode)
         } else {
           Decimal(decimal.toBigDecimal.setScale(_scale, mode), p, s)
         }
@@ -1644,10 +1644,9 @@ abstract class RoundBase(child: Expression, scale: 
Expression,
       case DecimalType.Fixed(p, s) =>
         if (_scale >= 0) {
           s"""
-            ${ev.value} = ${ce.value}.toPrecision(${ce.value}.precision(), $s,
-            Decimal.$modeStr(), true, null);
+            ${ev.value} = ${ce.value}.toPrecision($p, $s, Decimal.$modeStr(), 
true, null);
             ${ev.isNull} = ${ev.value} == null;"""
-       } else {
+        } else {
           s"""
             ${ev.value} = new Decimal().set(${ce.value}.toBigDecimal()
             .setScale(${_scale}, Decimal.$modeStr()), $p, $s);
diff --git 
a/sql/core/src/test/scala/org/apache/spark/sql/ApproximatePercentileQuerySuite.scala
 
b/sql/core/src/test/scala/org/apache/spark/sql/ApproximatePercentileQuerySuite.scala
index 3b987529afcb..a92218e1f1de 100644
--- 
a/sql/core/src/test/scala/org/apache/spark/sql/ApproximatePercentileQuerySuite.scala
+++ 
b/sql/core/src/test/scala/org/apache/spark/sql/ApproximatePercentileQuerySuite.scala
@@ -370,4 +370,16 @@ class ApproximatePercentileQuerySuite extends QueryTest 
with SharedSparkSession
       context = ExpectedContext(
         "", "", 8, 40, "percentile_approx(col, NULL, 100)"))
   }
+
+  test("SPARK-54750: percentile_approx returns NULL for certain decimal 
values") {
+    // Regression test: ROUND(PERCENTILE_APPROX(2150/1000.0, 0.95), 3) should 
return 2.15
+    checkAnswer(
+      spark.sql("SELECT ROUND(PERCENTILE_APPROX(2150 / 1000.0, 0.95), 3) as 
p95"),
+      Row(2.15)
+    )
+    checkAnswer(
+      spark.sql("SELECT ROUND(PERCENTILE_APPROX(2151 / 1000.0, 0.95), 3) as 
p95"),
+      Row(2.151)
+    )
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to