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

agrove pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-comet.git


The following commit(s) were added to refs/heads/main by this push:
     new acfd03cab feat:support ansi mode rounding function (#2542)
acfd03cab is described below

commit acfd03cabc806c2bf73aac7f3f3f634e2954a6f1
Author: B Vadlamani <[email protected]>
AuthorDate: Mon Oct 13 16:21:56 2025 -0700

    feat:support ansi mode rounding function (#2542)
---
 docs/source/user-guide/latest/expressions.md       |  4 +-
 native/core/src/execution/planner.rs               |  4 +-
 native/proto/src/proto/expr.proto                  |  1 +
 native/spark-expr/src/comet_scalar_funcs.rs        |  4 +-
 native/spark-expr/src/math_funcs/round.rs          | 87 ++++++++++++++++------
 .../org/apache/comet/serde/QueryPlanSerde.scala    |  6 +-
 .../scala/org/apache/comet/serde/arithmetic.scala  | 15 ++--
 .../main/scala/org/apache/comet/serde/arrays.scala |  2 +
 .../scala/org/apache/comet/serde/bitwise.scala     |  4 +-
 .../scala/org/apache/comet/serde/datetime.scala    |  7 +-
 .../main/scala/org/apache/comet/serde/hash.scala   | 10 ++-
 .../main/scala/org/apache/comet/serde/maps.scala   |  2 +-
 .../main/scala/org/apache/comet/serde/math.scala   | 15 +++-
 .../scala/org/apache/comet/serde/predicates.scala  |  2 +-
 .../org/apache/comet/CometExpressionSuite.scala    | 35 +++++++++
 15 files changed, 148 insertions(+), 50 deletions(-)

diff --git a/docs/source/user-guide/latest/expressions.md 
b/docs/source/user-guide/latest/expressions.md
index e727642dc..a255369ad 100644
--- a/docs/source/user-guide/latest/expressions.md
+++ b/docs/source/user-guide/latest/expressions.md
@@ -116,7 +116,7 @@ incompatible expressions.
 ## Math Expressions
 
 | Expression     | SQL       | Spark-Compatible? | Compatibility Notes         
      |
-| -------------- | --------- | ----------------- | 
--------------------------------- |
+| -------------- | --------- | ----------------- 
|-----------------------------------|
 | Acos           | `acos`    | Yes               |                             
      |
 | Add            | `+`       | Yes               |                             
      |
 | Asin           | `asin`    | Yes               |                             
      |
@@ -140,7 +140,7 @@ incompatible expressions.
 | Rand           | `rand`    | Yes               |                             
      |
 | Randn          | `randn`   | Yes               |                             
      |
 | Remainder      | `%`       | Yes               | ANSI mode is not supported. 
      |
-| Round          | `round`   | Yes               | ANSI mode is not supported. 
      |
+| Round          | `round`   | Yes               |                             
      |
 | Signum         | `signum`  | Yes               |                             
      |
 | Sin            | `sin`     | Yes               |                             
      |
 | Sqrt           | `sqrt`    | Yes               |                             
      |
diff --git a/native/core/src/execution/planner.rs 
b/native/core/src/execution/planner.rs
index 59090a5bd..1550efd79 100644
--- a/native/core/src/execution/planner.rs
+++ b/native/core/src/execution/planner.rs
@@ -2478,7 +2478,7 @@ impl PhysicalPlanner {
             fun_name,
             data_type.clone(),
             &self.session_ctx.state(),
-            None,
+            Some(expr.fail_on_error),
         )?;
 
         let args = args
@@ -3346,6 +3346,7 @@ mod tests {
                         func: "make_array".to_string(),
                         args: vec![array_col, array_col_1],
                         return_type: None,
+                        fail_on_error: false,
                     })),
                 }],
             })),
@@ -3464,6 +3465,7 @@ mod tests {
                         func: "array_repeat".to_string(),
                         args: vec![array_col, array_col_1],
                         return_type: None,
+                        fail_on_error: false,
                     })),
                 }],
             })),
diff --git a/native/proto/src/proto/expr.proto 
b/native/proto/src/proto/expr.proto
index ade9860c8..5853bc613 100644
--- a/native/proto/src/proto/expr.proto
+++ b/native/proto/src/proto/expr.proto
@@ -308,6 +308,7 @@ message ScalarFunc {
   string func = 1;
   repeated Expr args = 2;
   DataType return_type = 3;
+  bool fail_on_error = 4;
 }
 
 message CaseWhen {
diff --git a/native/spark-expr/src/comet_scalar_funcs.rs 
b/native/spark-expr/src/comet_scalar_funcs.rs
index 19fa11e64..fc0c096b1 100644
--- a/native/spark-expr/src/comet_scalar_funcs.rs
+++ b/native/spark-expr/src/comet_scalar_funcs.rs
@@ -99,6 +99,7 @@ pub fn create_comet_physical_fun_with_eval_mode(
     fail_on_error: Option<bool>,
     eval_mode: EvalMode,
 ) -> Result<Arc<ScalarUDF>, DataFusionError> {
+    let fail_on_error = fail_on_error.unwrap_or(false);
     match fun_name {
         "ceil" => {
             make_comet_scalar_udf!("ceil", spark_ceil, data_type)
@@ -119,7 +120,7 @@ pub fn create_comet_physical_fun_with_eval_mode(
             make_comet_scalar_udf!("lpad", func, without data_type)
         }
         "round" => {
-            make_comet_scalar_udf!("round", spark_round, data_type)
+            make_comet_scalar_udf!("round", spark_round, data_type, 
fail_on_error)
         }
         "unscaled_value" => {
             let func = Arc::new(spark_unscaled_value);
@@ -177,7 +178,6 @@ pub fn create_comet_physical_fun_with_eval_mode(
         }
         "spark_modulo" => {
             let func = Arc::new(spark_modulo);
-            let fail_on_error = fail_on_error.unwrap_or(false);
             make_comet_scalar_udf!("spark_modulo", func, without data_type, 
fail_on_error)
         }
         _ => registry.udf(fun_name).map_err(|e| {
diff --git a/native/spark-expr/src/math_funcs/round.rs 
b/native/spark-expr/src/math_funcs/round.rs
index 9191a88ca..d2cbe4f96 100644
--- a/native/spark-expr/src/math_funcs/round.rs
+++ b/native/spark-expr/src/math_funcs/round.rs
@@ -15,49 +15,81 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use crate::arithmetic_overflow_error;
 use crate::math_funcs::utils::{get_precision_scale, make_decimal_array, 
make_decimal_scalar};
 use arrow::array::{Array, ArrowNativeTypeOp};
 use arrow::array::{Int16Array, Int32Array, Int64Array, Int8Array};
 use arrow::datatypes::DataType;
+use arrow::error::ArrowError;
 use datafusion::common::{exec_err, internal_err, DataFusionError, ScalarValue};
 use datafusion::{functions::math::round::round, physical_plan::ColumnarValue};
 use std::{cmp::min, sync::Arc};
 
 macro_rules! integer_round {
-    ($X:expr, $DIV:expr, $HALF:expr) => {{
+    ($X:expr, $DIV:expr, $HALF:expr, $FAIL_ON_ERROR:expr) => {{
         let rem = $X % $DIV;
         if rem <= -$HALF {
-            ($X - rem).sub_wrapping($DIV)
+            if $FAIL_ON_ERROR {
+                ($X - rem).sub_checked($DIV).map_err(|_| {
+                    
ArrowError::ComputeError(arithmetic_overflow_error("integer").to_string())
+                })
+            } else {
+                Ok(($X - rem).sub_wrapping($DIV))
+            }
         } else if rem >= $HALF {
-            ($X - rem).add_wrapping($DIV)
+            if $FAIL_ON_ERROR {
+                ($X - rem).add_checked($DIV).map_err(|_| {
+                    
ArrowError::ComputeError(arithmetic_overflow_error("integer").to_string())
+                })
+            } else {
+                Ok(($X - rem).add_wrapping($DIV))
+            }
         } else {
-            $X - rem
+            if $FAIL_ON_ERROR {
+                $X.sub_checked(rem).map_err(|_| {
+                    
ArrowError::ComputeError(arithmetic_overflow_error("integer").to_string())
+                })
+            } else {
+                Ok($X.sub_wrapping(rem))
+            }
         }
     }};
 }
 
 macro_rules! round_integer_array {
-    ($ARRAY:expr, $POINT:expr, $TYPE:ty, $NATIVE:ty) => {{
+    ($ARRAY:expr, $POINT:expr, $TYPE:ty, $NATIVE:ty, $FAIL_ON_ERROR:expr) => {{
         let array = $ARRAY.as_any().downcast_ref::<$TYPE>().unwrap();
         let ten: $NATIVE = 10;
         let result: $TYPE = if let Some(div) = ten.checked_pow((-(*$POINT)) as 
u32) {
             let half = div / 2;
-            arrow::compute::kernels::arity::unary(array, |x| integer_round!(x, 
div, half))
+            arrow::compute::kernels::arity::try_unary(array, |x| {
+                integer_round!(x, div, half, $FAIL_ON_ERROR)
+            })?
         } else {
-            arrow::compute::kernels::arity::unary(array, |_| 0)
+            arrow::compute::kernels::arity::try_unary(array, |_| Ok(0))?
         };
         Ok(ColumnarValue::Array(Arc::new(result)))
     }};
 }
 
 macro_rules! round_integer_scalar {
-    ($SCALAR:expr, $POINT:expr, $TYPE:expr, $NATIVE:ty) => {{
+    ($SCALAR:expr, $POINT:expr, $TYPE:expr, $NATIVE:ty, $FAIL_ON_ERROR:expr) 
=> {{
         let ten: $NATIVE = 10;
         if let Some(div) = ten.checked_pow((-(*$POINT)) as u32) {
             let half = div / 2;
-            Ok(ColumnarValue::Scalar($TYPE(
-                $SCALAR.map(|x| integer_round!(x, div, half)),
-            )))
+            let scalar_opt = match $SCALAR {
+                Some(x) => match integer_round!(x, div, half, $FAIL_ON_ERROR) {
+                    Ok(v) => Some(v),
+                    Err(e) => {
+                        return Err(DataFusionError::ArrowError(
+                            Box::from(e),
+                            Some(DataFusionError::get_back_trace()),
+                        ))
+                    }
+                },
+                None => None,
+            };
+            Ok(ColumnarValue::Scalar($TYPE(scalar_opt)))
         } else {
             Ok(ColumnarValue::Scalar($TYPE(Some(0))))
         }
@@ -68,6 +100,7 @@ macro_rules! round_integer_scalar {
 pub fn spark_round(
     args: &[ColumnarValue],
     data_type: &DataType,
+    fail_on_error: bool,
 ) -> Result<ColumnarValue, DataFusionError> {
     let value = &args[0];
     let point = &args[1];
@@ -76,10 +109,18 @@ pub fn spark_round(
     };
     match value {
         ColumnarValue::Array(array) => match array.data_type() {
-            DataType::Int64 if *point < 0 => round_integer_array!(array, 
point, Int64Array, i64),
-            DataType::Int32 if *point < 0 => round_integer_array!(array, 
point, Int32Array, i32),
-            DataType::Int16 if *point < 0 => round_integer_array!(array, 
point, Int16Array, i16),
-            DataType::Int8 if *point < 0 => round_integer_array!(array, point, 
Int8Array, i8),
+            DataType::Int64 if *point < 0 => {
+                round_integer_array!(array, point, Int64Array, i64, 
fail_on_error)
+            }
+            DataType::Int32 if *point < 0 => {
+                round_integer_array!(array, point, Int32Array, i32, 
fail_on_error)
+            }
+            DataType::Int16 if *point < 0 => {
+                round_integer_array!(array, point, Int16Array, i16, 
fail_on_error)
+            }
+            DataType::Int8 if *point < 0 => {
+                round_integer_array!(array, point, Int8Array, i8, 
fail_on_error)
+            }
             DataType::Decimal128(_, scale) if *scale >= 0 => {
                 let f = decimal_round_f(scale, point);
                 let (precision, scale) = get_precision_scale(data_type);
@@ -93,16 +134,16 @@ pub fn spark_round(
         },
         ColumnarValue::Scalar(a) => match a {
             ScalarValue::Int64(a) if *point < 0 => {
-                round_integer_scalar!(a, point, ScalarValue::Int64, i64)
+                round_integer_scalar!(a, point, ScalarValue::Int64, i64, 
fail_on_error)
             }
             ScalarValue::Int32(a) if *point < 0 => {
-                round_integer_scalar!(a, point, ScalarValue::Int32, i32)
+                round_integer_scalar!(a, point, ScalarValue::Int32, i32, 
fail_on_error)
             }
             ScalarValue::Int16(a) if *point < 0 => {
-                round_integer_scalar!(a, point, ScalarValue::Int16, i16)
+                round_integer_scalar!(a, point, ScalarValue::Int16, i16, 
fail_on_error)
             }
             ScalarValue::Int8(a) if *point < 0 => {
-                round_integer_scalar!(a, point, ScalarValue::Int8, i8)
+                round_integer_scalar!(a, point, ScalarValue::Int8, i8, 
fail_on_error)
             }
             ScalarValue::Decimal128(a, _, scale) if *scale >= 0 => {
                 let f = decimal_round_f(scale, point);
@@ -158,7 +199,7 @@ mod test {
             ]))),
             ColumnarValue::Scalar(ScalarValue::Int64(Some(2))),
         ];
-        let ColumnarValue::Array(result) = spark_round(&args, 
&DataType::Float32)? else {
+        let ColumnarValue::Array(result) = spark_round(&args, 
&DataType::Float32, false)? else {
             unreachable!()
         };
         let floats = as_float32_array(&result)?;
@@ -176,7 +217,7 @@ mod test {
             ]))),
             ColumnarValue::Scalar(ScalarValue::Int64(Some(2))),
         ];
-        let ColumnarValue::Array(result) = spark_round(&args, 
&DataType::Float64)? else {
+        let ColumnarValue::Array(result) = spark_round(&args, 
&DataType::Float64, false)? else {
             unreachable!()
         };
         let floats = as_float64_array(&result)?;
@@ -193,7 +234,7 @@ mod test {
             ColumnarValue::Scalar(ScalarValue::Int64(Some(2))),
         ];
         let ColumnarValue::Scalar(ScalarValue::Float32(Some(result))) =
-            spark_round(&args, &DataType::Float32)?
+            spark_round(&args, &DataType::Float32, false)?
         else {
             unreachable!()
         };
@@ -209,7 +250,7 @@ mod test {
             ColumnarValue::Scalar(ScalarValue::Int64(Some(2))),
         ];
         let ColumnarValue::Scalar(ScalarValue::Float64(Some(result))) =
-            spark_round(&args, &DataType::Float64)?
+            spark_round(&args, &DataType::Float64, false)?
         else {
             unreachable!()
         };
diff --git a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala 
b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
index 0e91cd41f..afde79599 100644
--- a/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/QueryPlanSerde.scala
@@ -851,7 +851,7 @@ object QueryPlanSerde extends Logging with CometExprShim {
       case UnscaledValue(child) =>
         val childExpr = exprToProtoInternal(child, inputs, binding)
         val optExpr =
-          scalarFunctionExprToProtoWithReturnType("unscaled_value", LongType, 
childExpr)
+          scalarFunctionExprToProtoWithReturnType("unscaled_value", LongType, 
false, childExpr)
         optExprWithInfo(optExpr, expr, child)
 
       case MakeDecimal(child, precision, scale, true) =>
@@ -859,6 +859,7 @@ object QueryPlanSerde extends Logging with CometExprShim {
         val optExpr = scalarFunctionExprToProtoWithReturnType(
           "make_decimal",
           DecimalType(precision, scale),
+          false,
           childExpr)
         optExprWithInfo(optExpr, expr, child)
 
@@ -967,9 +968,11 @@ object QueryPlanSerde extends Logging with CometExprShim {
   def scalarFunctionExprToProtoWithReturnType(
       funcName: String,
       returnType: DataType,
+      failOnError: Boolean,
       args: Option[Expr]*): Option[Expr] = {
     val builder = ExprOuterClass.ScalarFunc.newBuilder()
     builder.setFunc(funcName)
+    builder.setFailOnError(failOnError)
     serializeDataType(returnType).flatMap { t =>
       builder.setReturnType(t)
       scalarFunctionExprToProto0(builder, args: _*)
@@ -979,6 +982,7 @@ object QueryPlanSerde extends Logging with CometExprShim {
   def scalarFunctionExprToProto(funcName: String, args: Option[Expr]*): 
Option[Expr] = {
     val builder = ExprOuterClass.ScalarFunc.newBuilder()
     builder.setFunc(funcName)
+    builder.setFailOnError(false)
     scalarFunctionExprToProto0(builder, args: _*)
   }
 
diff --git a/spark/src/main/scala/org/apache/comet/serde/arithmetic.scala 
b/spark/src/main/scala/org/apache/comet/serde/arithmetic.scala
index eed4d7b16..a97a87e73 100644
--- a/spark/src/main/scala/org/apache/comet/serde/arithmetic.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/arithmetic.scala
@@ -279,14 +279,6 @@ object CometRemainder extends 
CometExpressionSerde[Remainder] with MathBase {
 
 object CometRound extends CometExpressionSerde[Round] {
 
-  override def getSupportLevel(expr: Round): SupportLevel = {
-    if (expr.ansiEnabled) {
-      Incompatible(Some("ANSI mode is not supported"))
-    } else {
-      Compatible(None)
-    }
-  }
-
   override def convert(
       r: Round,
       inputs: Seq[Attribute],
@@ -325,7 +317,12 @@ object CometRound extends CometExpressionSerde[Round] {
         // `scale` must be Int64 type in DataFusion
         val scaleExpr = exprToProtoInternal(Literal(_scale.toLong, LongType), 
inputs, binding)
         val optExpr =
-          scalarFunctionExprToProtoWithReturnType("round", r.dataType, 
childExpr, scaleExpr)
+          scalarFunctionExprToProtoWithReturnType(
+            "round",
+            r.dataType,
+            r.ansiEnabled,
+            childExpr,
+            scaleExpr)
         optExprWithInfo(optExpr, r, r.child)
     }
 
diff --git a/spark/src/main/scala/org/apache/comet/serde/arrays.scala 
b/spark/src/main/scala/org/apache/comet/serde/arrays.scala
index 334f8ee8b..e8a4ce76f 100644
--- a/spark/src/main/scala/org/apache/comet/serde/arrays.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/arrays.scala
@@ -210,6 +210,7 @@ object CometArraysOverlap extends 
CometExpressionSerde[ArraysOverlap] {
     val arraysOverlapScalarExpr = scalarFunctionExprToProtoWithReturnType(
       "array_has_any",
       BooleanType,
+      false,
       leftArrayExprProto,
       rightArrayExprProto)
     optExprWithInfo(arraysOverlapScalarExpr, expr, expr.children: _*)
@@ -250,6 +251,7 @@ object CometArrayCompact extends 
CometExpressionSerde[Expression] {
     val arrayCompactScalarExpr = scalarFunctionExprToProtoWithReturnType(
       "array_remove_all",
       ArrayType(elementType = elementType),
+      false,
       arrayExprProto,
       nullLiteralProto)
     optExprWithInfo(arrayCompactScalarExpr, expr, expr.children: _*)
diff --git a/spark/src/main/scala/org/apache/comet/serde/bitwise.scala 
b/spark/src/main/scala/org/apache/comet/serde/bitwise.scala
index 8215ea5df..56404fe3c 100644
--- a/spark/src/main/scala/org/apache/comet/serde/bitwise.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/bitwise.scala
@@ -135,7 +135,7 @@ object CometBitwiseGet extends 
CometExpressionSerde[BitwiseGet] {
     val argProto = exprToProto(expr.left, inputs, binding)
     val posProto = exprToProto(expr.right, inputs, binding)
     val bitGetScalarExpr =
-      scalarFunctionExprToProtoWithReturnType("bit_get", ByteType, argProto, 
posProto)
+      scalarFunctionExprToProtoWithReturnType("bit_get", ByteType, false, 
argProto, posProto)
     optExprWithInfo(bitGetScalarExpr, expr, expr.children: _*)
   }
 }
@@ -147,7 +147,7 @@ object CometBitwiseCount extends 
CometExpressionSerde[BitwiseCount] {
       binding: Boolean): Option[ExprOuterClass.Expr] = {
     val childProto = exprToProto(expr.child, inputs, binding)
     val bitCountScalarExpr =
-      scalarFunctionExprToProtoWithReturnType("bit_count", IntegerType, 
childProto)
+      scalarFunctionExprToProtoWithReturnType("bit_count", IntegerType, false, 
childProto)
     optExprWithInfo(bitCountScalarExpr, expr, expr.children: _*)
   }
 }
diff --git a/spark/src/main/scala/org/apache/comet/serde/datetime.scala 
b/spark/src/main/scala/org/apache/comet/serde/datetime.scala
index 9473ee30e..267b2b441 100644
--- a/spark/src/main/scala/org/apache/comet/serde/datetime.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/datetime.scala
@@ -263,7 +263,12 @@ object CometTruncDate extends 
CometExpressionSerde[TruncDate] {
     val childExpr = exprToProtoInternal(expr.date, inputs, binding)
     val formatExpr = exprToProtoInternal(expr.format, inputs, binding)
     val optExpr =
-      scalarFunctionExprToProtoWithReturnType("date_trunc", DateType, 
childExpr, formatExpr)
+      scalarFunctionExprToProtoWithReturnType(
+        "date_trunc",
+        DateType,
+        false,
+        childExpr,
+        formatExpr)
     optExprWithInfo(optExpr, expr, expr.date, expr.format)
   }
 }
diff --git a/spark/src/main/scala/org/apache/comet/serde/hash.scala 
b/spark/src/main/scala/org/apache/comet/serde/hash.scala
index 5c45a2593..a384ecf44 100644
--- a/spark/src/main/scala/org/apache/comet/serde/hash.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/hash.scala
@@ -40,7 +40,7 @@ object CometXxHash64 extends CometExpressionSerde[XxHash64] {
       .setLongVal(expr.seed)
     val seedExpr = 
Some(ExprOuterClass.Expr.newBuilder().setLiteral(seedBuilder).build())
     // the seed is put at the end of the arguments
-    scalarFunctionExprToProtoWithReturnType("xxhash64", LongType, exprs :+ 
seedExpr: _*)
+    scalarFunctionExprToProtoWithReturnType("xxhash64", LongType, false, exprs 
:+ seedExpr: _*)
   }
 }
 
@@ -59,7 +59,11 @@ object CometMurmur3Hash extends 
CometExpressionSerde[Murmur3Hash] {
       .setIntVal(expr.seed)
     val seedExpr = 
Some(ExprOuterClass.Expr.newBuilder().setLiteral(seedBuilder).build())
     // the seed is put at the end of the arguments
-    scalarFunctionExprToProtoWithReturnType("murmur3_hash", IntegerType, exprs 
:+ seedExpr: _*)
+    scalarFunctionExprToProtoWithReturnType(
+      "murmur3_hash",
+      IntegerType,
+      false,
+      exprs :+ seedExpr: _*)
   }
 }
 
@@ -81,7 +85,7 @@ object CometSha2 extends CometExpressionSerde[Sha2] {
 
     val leftExpr = exprToProtoInternal(expr.left, inputs, binding)
     val numBitsExpr = exprToProtoInternal(expr.right, inputs, binding)
-    scalarFunctionExprToProtoWithReturnType("sha2", StringType, leftExpr, 
numBitsExpr)
+    scalarFunctionExprToProtoWithReturnType("sha2", StringType, false, 
leftExpr, numBitsExpr)
   }
 }
 
diff --git a/spark/src/main/scala/org/apache/comet/serde/maps.scala 
b/spark/src/main/scala/org/apache/comet/serde/maps.scala
index 572ac37d4..2e217f6af 100644
--- a/spark/src/main/scala/org/apache/comet/serde/maps.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/maps.scala
@@ -85,7 +85,7 @@ object CometMapFromArrays extends 
CometExpressionSerde[MapFromArrays] {
     val valueType = expr.right.dataType.asInstanceOf[ArrayType].elementType
     val returnType = MapType(keyType = keyType, valueType = valueType)
     val mapFromArraysExpr =
-      scalarFunctionExprToProtoWithReturnType("map", returnType, keysExpr, 
valuesExpr)
+      scalarFunctionExprToProtoWithReturnType("map", returnType, false, 
keysExpr, valuesExpr)
     optExprWithInfo(mapFromArraysExpr, expr, expr.children: _*)
   }
 }
diff --git a/spark/src/main/scala/org/apache/comet/serde/math.scala 
b/spark/src/main/scala/org/apache/comet/serde/math.scala
index f2b0010d8..bfcd242d7 100644
--- a/spark/src/main/scala/org/apache/comet/serde/math.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/math.scala
@@ -50,7 +50,8 @@ object CometCeil extends CometExpressionSerde[Ceil] {
         withInfo(expr, s"Decimal type $t has negative scale")
         None
       case _ =>
-        val optExpr = scalarFunctionExprToProtoWithReturnType("ceil", 
expr.dataType, childExpr)
+        val optExpr =
+          scalarFunctionExprToProtoWithReturnType("ceil", expr.dataType, 
false, childExpr)
         optExprWithInfo(optExpr, expr, expr.child)
     }
   }
@@ -69,7 +70,8 @@ object CometFloor extends CometExpressionSerde[Floor] {
         withInfo(expr, s"Decimal type $t has negative scale")
         None
       case _ =>
-        val optExpr = scalarFunctionExprToProtoWithReturnType("floor", 
expr.dataType, childExpr)
+        val optExpr =
+          scalarFunctionExprToProtoWithReturnType("floor", expr.dataType, 
false, childExpr)
         optExprWithInfo(optExpr, expr, expr.child)
     }
   }
@@ -118,7 +120,7 @@ object CometHex extends CometExpressionSerde[Hex] with 
MathExprBase {
       inputs: Seq[Attribute],
       binding: Boolean): Option[ExprOuterClass.Expr] = {
     val childExpr = exprToProtoInternal(expr.child, inputs, binding)
-    val optExpr = scalarFunctionExprToProtoWithReturnType("hex", 
expr.dataType, childExpr)
+    val optExpr = scalarFunctionExprToProtoWithReturnType("hex", 
expr.dataType, false, childExpr)
     optExprWithInfo(optExpr, expr, expr.child)
   }
 }
@@ -132,7 +134,12 @@ object CometUnhex extends CometExpressionSerde[Unhex] with 
MathExprBase {
     val failOnErrorExpr = exprToProtoInternal(Literal(expr.failOnError), 
inputs, binding)
 
     val optExpr =
-      scalarFunctionExprToProtoWithReturnType("unhex", expr.dataType, 
childExpr, failOnErrorExpr)
+      scalarFunctionExprToProtoWithReturnType(
+        "unhex",
+        expr.dataType,
+        false,
+        childExpr,
+        failOnErrorExpr)
     optExprWithInfo(optExpr, expr, expr.child)
   }
 }
diff --git a/spark/src/main/scala/org/apache/comet/serde/predicates.scala 
b/spark/src/main/scala/org/apache/comet/serde/predicates.scala
index 00a1fb6fa..2e253bc23 100644
--- a/spark/src/main/scala/org/apache/comet/serde/predicates.scala
+++ b/spark/src/main/scala/org/apache/comet/serde/predicates.scala
@@ -218,7 +218,7 @@ object CometIsNaN extends CometExpressionSerde[IsNaN] {
       inputs: Seq[Attribute],
       binding: Boolean): Option[ExprOuterClass.Expr] = {
     val childExpr = exprToProtoInternal(expr.child, inputs, binding)
-    val optExpr = scalarFunctionExprToProtoWithReturnType("isnan", 
BooleanType, childExpr)
+    val optExpr = scalarFunctionExprToProtoWithReturnType("isnan", 
BooleanType, false, childExpr)
 
     optExprWithInfo(optExpr, expr, expr.child)
   }
diff --git a/spark/src/test/scala/org/apache/comet/CometExpressionSuite.scala 
b/spark/src/test/scala/org/apache/comet/CometExpressionSuite.scala
index 27c9124f1..9085c0fa2 100644
--- a/spark/src/test/scala/org/apache/comet/CometExpressionSuite.scala
+++ b/spark/src/test/scala/org/apache/comet/CometExpressionSuite.scala
@@ -3017,6 +3017,41 @@ class CometExpressionSuite extends CometTestBase with 
AdaptiveSparkPlanHelper {
     }
   }
 
+  test("ANSI support for round function") {
+    Seq(
+      (
+        Int.MaxValue,
+        Int.MinValue,
+        Long.MinValue,
+        Long.MaxValue,
+        Byte.MinValue,
+        Byte.MaxValue,
+        Short.MinValue,
+        Short.MaxValue)).foreach { value =>
+      val data = Seq(value)
+      withParquetTable(data, "tbl") {
+        Seq(-1000, -100, -10, -1, 0, 1, 10, 100, 1000).foreach { scale =>
+          Seq(true, false).foreach { ansi =>
+            withSQLConf(SQLConf.ANSI_ENABLED.key -> ansi.toString) {
+              val res = spark.sql(s"SELECT round(_1, $scale) from tbl")
+              checkSparkMaybeThrows(res) match {
+                case (Some(sparkException), Some(cometException)) =>
+                  
assert(sparkException.getMessage.contains("ARITHMETIC_OVERFLOW"))
+                  
assert(cometException.getMessage.contains("ARITHMETIC_OVERFLOW"))
+                case (None, None) => checkSparkAnswerAndOperator(res)
+                case (None, Some(ex)) =>
+                  fail("Comet threw an exception but Spark did not. Comet 
exception: " + ex.getMessage)
+                case (Some(sparkException), None) =>
+                  fail("Spark threw an exception but Comet did not. Spark 
exception: " +
+                    sparkException.getMessage)
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
   test("test integral divide overflow for decimal") {
     if (isSpark40Plus) {
       Seq(true, false)


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

Reply via email to