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

zml1206 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new aa0bcc8d4d [GLUTEN-11918][VL] Fall back Cast when per-expression 
timezone differs from session timezone (#12048)
aa0bcc8d4d is described below

commit aa0bcc8d4d571f49ddafca0f4a5a2448f3fdfa9b
Author: Yao-MR <[email protected]>
AuthorDate: Fri May 8 17:16:44 2026 +0800

    [GLUTEN-11918][VL] Fall back Cast when per-expression timezone differs from 
session timezone (#12048)
---
 .../gluten/expression/ExpressionConverter.scala    | 29 ++++++++++++++++++++++
 .../gluten/utils/velox/VeloxTestSettings.scala     |  2 +-
 .../gluten/utils/velox/VeloxTestSettings.scala     |  2 +-
 3 files changed, 31 insertions(+), 2 deletions(-)

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..c50bae6e77 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
@@ -467,6 +467,22 @@ object ExpressionConverter extends SQLConfHelper with 
Logging {
       case s: ScalarSubquery =>
         ScalarSubqueryTransformer(substraitExprName, s)
       case c: Cast =>
+        // Gluten uses session-level timezone for cast. If the per-expression 
timezone
+        // differs from session timezone and the cast involves timestamp type, 
we must
+        // fall back to Spark native execution to ensure correctness.
+        // Note: Spark Cast applies zoneId recursively to array/map/struct 
elements,
+        // so we must check nested types as well.
+        c.timeZoneId.foreach {
+          tz =>
+            val sessionTz = SQLConf.get.sessionLocalTimeZone
+            if (tz != sessionTz) {
+              if (involvesTimestampType(c.child.dataType) || 
involvesTimestampType(c.dataType)) {
+                throw new GlutenNotSupportException(
+                  s"Cast with per-expression timezone '$tz' different from 
session timezone " +
+                    s"'$sessionTz' is not supported when timestamp type is 
involved")
+              }
+            }
+        }
         // Add trim node, as necessary.
         val newCast =
           BackendsApiManager.getSparkPlanExecApiInstance.genCastWithNewChild(c)
@@ -915,6 +931,19 @@ object ExpressionConverter extends SQLConfHelper with 
Logging {
     }
   }
 
+  /**
+   * Recursively checks whether the given data type is, or contains, a 
TimestampType, including
+   * nested array/map/struct/UDT element types.
+   */
+  private def involvesTimestampType(dataType: DataType): Boolean = dataType 
match {
+    case TimestampType => true
+    case a: ArrayType => involvesTimestampType(a.elementType)
+    case m: MapType => involvesTimestampType(m.keyType) || 
involvesTimestampType(m.valueType)
+    case s: StructType => s.exists(f => involvesTimestampType(f.dataType))
+    case udt: UserDefinedType[_] => involvesTimestampType(udt.sqlType)
+    case _ => false
+  }
+
   private def getAndCheckSubstraitName(
       expr: Expression,
       expressionsMap: Map[Class[_], String]): String = {
diff --git 
a/gluten-ut/spark40/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
 
b/gluten-ut/spark40/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
index ba8c773c97..f639f9c39c 100644
--- 
a/gluten-ut/spark40/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
+++ 
b/gluten-ut/spark40/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
@@ -249,7 +249,7 @@ class VeloxTestSettings extends BackendTestSettings {
   // is in test-jar without shaded Guava, while SubExprEvaluationRuntime is 
shaded.
   enableSuite[GlutenSubexpressionEliminationSuite]
   enableSuite[GlutenTimeWindowSuite]
-  // TODO: 4.x enableSuite[GlutenToPrettyStringSuite]  // 1 failure
+  enableSuite[GlutenToPrettyStringSuite]
   enableSuite[GlutenUnsafeRowConverterSuite]
   enableSuite[GlutenUnwrapUDTExpressionSuite]
   enableSuite[GlutenV2ExpressionUtilsSuite]
diff --git 
a/gluten-ut/spark41/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
 
b/gluten-ut/spark41/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
index 3e32d6b559..29a1bfd685 100644
--- 
a/gluten-ut/spark41/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
+++ 
b/gluten-ut/spark41/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
@@ -260,7 +260,7 @@ class VeloxTestSettings extends BackendTestSettings {
   // is in test-jar without shaded Guava, while SubExprEvaluationRuntime is 
shaded.
   enableSuite[GlutenSubexpressionEliminationSuite]
   enableSuite[GlutenTimeWindowSuite]
-  // TODO: 4.x enableSuite[GlutenToPrettyStringSuite]  // 1 failure
+  enableSuite[GlutenToPrettyStringSuite]
   enableSuite[GlutenUnsafeRowConverterSuite]
   enableSuite[GlutenUnwrapUDTExpressionSuite]
   enableSuite[GlutenV2ExpressionUtilsSuite]


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

Reply via email to