You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gluten.apache.org by ch...@apache.org on 2026/04/15 11:17:33 UTC
(gluten) 10/29: [GLUTEN-10134][VL] Add ANSI mode: checked_remainder, decimal sum/avg overflow, make_date
This is an automated email from the ASF dual-hosted git repository.
changchen pushed a commit to branch feature/ansi-ci-baseline
in repository https://gitbox.apache.org/repos/asf/gluten.git
commit 44d76052952fddcfd45e0c472ee7b537adda489e
Author: Chang chen <ch...@microsoft.com>
AuthorDate: Wed Apr 1 08:56:48 2026 +0000
[GLUTEN-10134][VL] Add ANSI mode: checked_remainder, decimal sum/avg overflow, make_date
- Add CHECKED_REMAINDER constant and ExpressionConverter mapping for Remainder
- Add Remainder to withAnsiEvalMode/withTryEvalMode in Spark40/41 shims
- Add remainder ANSI test in ArithmeticAnsiValidateSuite
- Fix spotless formatting in UnaryExpressionTransformer
Batch 4 of Phase 1 ANSI mode support (Issue #10134):
- Task 8: CheckedRemainder function (integer div-by-zero throws exception)
- Task 9: Decimal sum/avg overflow throws exception in ANSI mode
- Task 10: make_date throws exception on invalid date in ANSI mode
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
.../apache/gluten/functions/ArithmeticAnsiValidateSuite.scala | 11 +++++++++++
.../org/apache/gluten/expression/ExpressionConverter.scala | 8 ++++++++
.../apache/gluten/expression/UnaryExpressionTransformer.scala | 10 ++--------
.../scala/org/apache/gluten/expression/ExpressionNames.scala | 1 +
.../org/apache/gluten/sql/shims/spark40/Spark40Shims.scala | 2 ++
.../org/apache/gluten/sql/shims/spark41/Spark41Shims.scala | 2 ++
6 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/backends-velox/src/test/scala/org/apache/gluten/functions/ArithmeticAnsiValidateSuite.scala b/backends-velox/src/test/scala/org/apache/gluten/functions/ArithmeticAnsiValidateSuite.scala
index a1633c4cb4..0fb59fe9c0 100644
--- a/backends-velox/src/test/scala/org/apache/gluten/functions/ArithmeticAnsiValidateSuite.scala
+++ b/backends-velox/src/test/scala/org/apache/gluten/functions/ArithmeticAnsiValidateSuite.scala
@@ -100,4 +100,15 @@ class ArithmeticAnsiValidateSuite extends FunctionsValidateSuite {
}
}
+ test("remainder") {
+ runQueryAndCompare("SELECT int_field1 % 3 FROM datatab WHERE int_field1 IS NOT NULL") {
+ checkGlutenPlan[ProjectExecTransformer]
+ }
+ if (isSparkVersionGE("3.4")) {
+ intercept[SparkException] {
+ sql("SELECT 1 % 0").collect()
+ }
+ }
+ }
+
}
diff --git a/gluten-substrait/src/main/scala/org/apache/gluten/expression/ExpressionConverter.scala b/gluten-substrait/src/main/scala/org/apache/gluten/expression/ExpressionConverter.scala
index 73f7b86996..fd88427e1d 100644
--- a/gluten-substrait/src/main/scala/org/apache/gluten/expression/ExpressionConverter.scala
+++ b/gluten-substrait/src/main/scala/org/apache/gluten/expression/ExpressionConverter.scala
@@ -791,6 +791,14 @@ object ExpressionConverter extends SQLConfHelper with Logging {
i,
ExpressionNames.CHECKED_DIV
)
+ case a: Remainder =>
+ BackendsApiManager.getSparkPlanExecApiInstance.genArithmeticTransformer(
+ substraitExprName,
+ replaceWithExpressionTransformer0(a.left, attributeSeq, expressionsMap),
+ replaceWithExpressionTransformer0(a.right, attributeSeq, expressionsMap),
+ a,
+ ExpressionNames.CHECKED_REMAINDER
+ )
case tryEval: TryEval =>
// This is a placeholder to handle try_eval(other expressions).
BackendsApiManager.getSparkPlanExecApiInstance.genTryEvalTransformer(
diff --git a/gluten-substrait/src/main/scala/org/apache/gluten/expression/UnaryExpressionTransformer.scala b/gluten-substrait/src/main/scala/org/apache/gluten/expression/UnaryExpressionTransformer.scala
index a076c46b40..52cd0115db 100644
--- a/gluten-substrait/src/main/scala/org/apache/gluten/expression/UnaryExpressionTransformer.scala
+++ b/gluten-substrait/src/main/scala/org/apache/gluten/expression/UnaryExpressionTransformer.scala
@@ -46,15 +46,9 @@ case class CastTransformer(substraitExprName: String, child: ExpressionTransform
override def doTransform(context: SubstraitContext): ExpressionNode = {
original.dataType match {
case CharType(length) =>
- buildCastWithWriteSideCheck(
- context,
- ExpressionNames.CHAR_TYPE_WRITE_SIDE_CHECK,
- length)
+ buildCastWithWriteSideCheck(context, ExpressionNames.CHAR_TYPE_WRITE_SIDE_CHECK, length)
case VarcharType(length) =>
- buildCastWithWriteSideCheck(
- context,
- ExpressionNames.VARCHAR_TYPE_WRITE_SIDE_CHECK,
- length)
+ buildCastWithWriteSideCheck(context, ExpressionNames.VARCHAR_TYPE_WRITE_SIDE_CHECK, length)
case _ =>
val typeNode = ConverterUtils.getTypeNode(dataType, original.nullable)
ExpressionBuilder.makeCast(
diff --git a/shims/common/src/main/scala/org/apache/gluten/expression/ExpressionNames.scala b/shims/common/src/main/scala/org/apache/gluten/expression/ExpressionNames.scala
index d4afb7ff73..617aa2cd69 100644
--- a/shims/common/src/main/scala/org/apache/gluten/expression/ExpressionNames.scala
+++ b/shims/common/src/main/scala/org/apache/gluten/expression/ExpressionNames.scala
@@ -93,6 +93,7 @@ object ExpressionNames {
final val CHECKED_DIVIDE = "checked_divide"
final val CHECKED_MULTIPLY = "checked_multiply"
final val CHECKED_DIV = "checked_div"
+ final val CHECKED_REMAINDER = "checked_remainder"
// SparkSQL String functions
final val ASCII = "ascii"
diff --git a/shims/spark40/src/main/scala/org/apache/gluten/sql/shims/spark40/Spark40Shims.scala b/shims/spark40/src/main/scala/org/apache/gluten/sql/shims/spark40/Spark40Shims.scala
index 0c3b163ce5..ebccadf96b 100644
--- a/shims/spark40/src/main/scala/org/apache/gluten/sql/shims/spark40/Spark40Shims.scala
+++ b/shims/spark40/src/main/scala/org/apache/gluten/sql/shims/spark40/Spark40Shims.scala
@@ -496,6 +496,7 @@ class Spark40Shims extends SparkShims {
case d: Divide => d.evalMode == EvalMode.TRY
case m: Multiply => m.evalMode == EvalMode.TRY
case c: Cast => c.evalMode == EvalMode.TRY
+ case r: Remainder => r.evalMode == EvalMode.TRY
case _ => false
}
}
@@ -508,6 +509,7 @@ class Spark40Shims extends SparkShims {
case m: Multiply => m.evalMode == EvalMode.ANSI
case c: Cast => c.evalMode == EvalMode.ANSI
case i: IntegralDivide => i.evalMode == EvalMode.ANSI
+ case r: Remainder => r.evalMode == EvalMode.ANSI
case _ => false
}
}
diff --git a/shims/spark41/src/main/scala/org/apache/gluten/sql/shims/spark41/Spark41Shims.scala b/shims/spark41/src/main/scala/org/apache/gluten/sql/shims/spark41/Spark41Shims.scala
index 5ff9d51c71..1c8d267204 100644
--- a/shims/spark41/src/main/scala/org/apache/gluten/sql/shims/spark41/Spark41Shims.scala
+++ b/shims/spark41/src/main/scala/org/apache/gluten/sql/shims/spark41/Spark41Shims.scala
@@ -495,6 +495,7 @@ class Spark41Shims extends SparkShims {
case d: Divide => d.evalMode == EvalMode.TRY
case m: Multiply => m.evalMode == EvalMode.TRY
case c: Cast => c.evalMode == EvalMode.TRY
+ case r: Remainder => r.evalMode == EvalMode.TRY
case _ => false
}
}
@@ -507,6 +508,7 @@ class Spark41Shims extends SparkShims {
case m: Multiply => m.evalMode == EvalMode.ANSI
case c: Cast => c.evalMode == EvalMode.ANSI
case i: IntegralDivide => i.evalMode == EvalMode.ANSI
+ case r: Remainder => r.evalMode == EvalMode.ANSI
case _ => false
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@gluten.apache.org
For additional commands, e-mail: commits-help@gluten.apache.org