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

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


The following commit(s) were added to refs/heads/main by this push:
     new d5d2aca32a [GLUTEN-8332][VL] Support explode/posexplode/inline outer 
(#10202)
d5d2aca32a is described below

commit d5d2aca32ab73b3e088ed9d930fb3ecf37698f72
Author: Rong Ma <[email protected]>
AuthorDate: Fri Jul 18 10:57:43 2025 +0100

    [GLUTEN-8332][VL] Support explode/posexplode/inline outer (#10202)
---
 .../gluten/execution/GenerateExecTransformer.scala | 105 +++++++--
 .../gluten/execution/MiscOperatorSuite.scala       | 256 ++++++++++++---------
 cpp/velox/substrait/SubstraitToVeloxPlan.cc        |  14 +-
 .../gluten/utils/velox/VeloxTestSettings.scala     |   1 +
 .../GlutenGeneratorExpressionSuite.scala           |  21 ++
 .../gluten/utils/velox/VeloxTestSettings.scala     |   1 +
 .../GlutenGeneratorExpressionSuite.scala           |  21 ++
 .../gluten/utils/velox/VeloxTestSettings.scala     |   1 +
 .../GlutenGeneratorExpressionSuite.scala           |  21 ++
 .../gluten/utils/velox/VeloxTestSettings.scala     |   1 +
 .../GlutenGeneratorExpressionSuite.scala           |  21 ++
 11 files changed, 317 insertions(+), 146 deletions(-)

diff --git 
a/backends-velox/src/main/scala/org/apache/gluten/execution/GenerateExecTransformer.scala
 
b/backends-velox/src/main/scala/org/apache/gluten/execution/GenerateExecTransformer.scala
index b5766c35c3..e2d257c0c0 100644
--- 
a/backends-velox/src/main/scala/org/apache/gluten/execution/GenerateExecTransformer.scala
+++ 
b/backends-velox/src/main/scala/org/apache/gluten/execution/GenerateExecTransformer.scala
@@ -28,7 +28,7 @@ import org.apache.gluten.utils.PullOutProjectHelper
 import org.apache.spark.sql.catalyst.expressions._
 import org.apache.spark.sql.execution.{GenerateExec, ProjectExec, SparkPlan}
 import org.apache.spark.sql.execution.metric.SQLMetrics
-import org.apache.spark.sql.types.IntegerType
+import org.apache.spark.sql.types.{BooleanType, IntegerType}
 
 import com.google.protobuf.StringValue
 
@@ -70,7 +70,7 @@ case class GenerateExecTransformer(
   override protected def doGeneratorValidate(
       generator: Generator,
       outer: Boolean): ValidationResult = {
-    if (!supportsGenerate(generator, outer)) {
+    if (!supportsGenerate(generator)) {
       ValidationResult.failed(
         s"Velox backend does not support this generator: 
${generator.getClass.getSimpleName}" +
           s", outer: $outer")
@@ -132,6 +132,12 @@ case class GenerateExecTransformer(
         .append(if (isStack) "1" else "0")
         .append("\n")
 
+      // isOuter: 1 for outer, 0 for inner.
+      parametersStr
+        .append("isOuter=")
+        .append(if (outer) "1" else "0")
+        .append("\n")
+
       val injectProject = if (isStack) {
         // We always need to inject a Project for stack because we organize
         // stack's flat params into arrays, e.g. stack(2, 1, 2, 3) is
@@ -161,17 +167,12 @@ case class GenerateExecTransformer(
 }
 
 object GenerateExecTransformer {
-  def supportsGenerate(generator: Generator, outer: Boolean): Boolean = {
-    // TODO: supports outer and remove this param.
-    if (outer) {
-      false
-    } else {
-      generator match {
-        case _: Inline | _: ExplodeBase | _: JsonTuple | _: Stack =>
-          true
-        case _ =>
-          false
-      }
+  def supportsGenerate(generator: Generator): Boolean = {
+    generator match {
+      case _: Inline | _: ExplodeBase | _: JsonTuple | _: Stack =>
+        true
+      case _ =>
+        false
     }
   }
 }
@@ -179,7 +180,7 @@ object GenerateExecTransformer {
 object PullOutGenerateProjectHelper extends PullOutProjectHelper {
   val JSON_PATH_PREFIX = "$."
   def pullOutPreProject(generate: GenerateExec): SparkPlan = {
-    if (GenerateExecTransformer.supportsGenerate(generate.generator, 
generate.outer)) {
+    if (GenerateExecTransformer.supportsGenerate(generate.generator)) {
       generate.generator match {
         case _: Inline | _: ExplodeBase =>
           val expressionMap = new mutable.HashMap[Expression, 
NamedExpression]()
@@ -277,7 +278,7 @@ object PullOutGenerateProjectHelper extends 
PullOutProjectHelper {
   }
 
   def pullOutPostProject(generate: GenerateExec): SparkPlan = {
-    if (GenerateExecTransformer.supportsGenerate(generate.generator, 
generate.outer)) {
+    if (GenerateExecTransformer.supportsGenerate(generate.generator)) {
       generate.generator match {
         case PosExplode(_) =>
           val originalOrdinal = generate.generatorOutput.head
@@ -287,22 +288,76 @@ object PullOutGenerateProjectHelper extends 
PullOutProjectHelper {
               originalOrdinal.exprId,
               originalOrdinal.qualifier)
           }
-          val newGenerate =
-            generate.copy(generatorOutput = generate.generatorOutput.tail :+ 
originalOrdinal)
-          ProjectExec(
-            (generate.requiredChildOutput :+ ordinal) ++ 
generate.generatorOutput.tail,
-            newGenerate)
+
+          if (generate.outer) {
+            val isNullOrEmpty =
+              AttributeReference(generatePostAliasName, BooleanType, nullable 
= true)()
+
+            val newOutput = (ordinal +: generate.generatorOutput.tail).map {
+              attr =>
+                val caseWhen = CaseWhen(
+                  Seq((isNullOrEmpty, Literal(null, attr.dataType))),
+                  attr
+                )
+                Alias(caseWhen, generatePostAliasName)(attr.exprId, 
attr.qualifier)
+            }
+
+            // Reorder the generatorOutput to match the output from the Unnest 
operator in Velox.
+            val newGenerate = generate.copy(generatorOutput =
+              generate.generatorOutput.tail :+ originalOrdinal :+ 
isNullOrEmpty)
+
+            ProjectExec(generate.requiredChildOutput ++ newOutput, newGenerate)
+          } else {
+            val newGenerate =
+              generate.copy(generatorOutput = generate.generatorOutput.tail :+ 
originalOrdinal)
+            ProjectExec(
+              (generate.requiredChildOutput :+ ordinal) ++ 
generate.generatorOutput.tail,
+              newGenerate)
+          }
         case Inline(_) | JsonTupleExplode(_) =>
           val unnestOutput = {
             val struct = CreateStruct(generate.generatorOutput)
             val alias = Alias(struct, generatePostAliasName)()
             alias.toAttribute
           }
-          val newGenerate = generate.copy(generatorOutput = Seq(unnestOutput))
-          val newOutput = generate.generatorOutput.zipWithIndex.map {
-            case (attr, i) =>
-              val getStructField = GetStructField(unnestOutput, i, 
Some(attr.name))
-              Alias(getStructField, generatePostAliasName)(attr.exprId, 
attr.qualifier)
+          if (generate.outer) {
+            val isNullOrEmpty =
+              AttributeReference(generatePostAliasName, BooleanType, nullable 
= true)()
+            val newGenerate = generate.copy(generatorOutput = 
Seq(unnestOutput) :+ isNullOrEmpty)
+            val newOutput = generate.generatorOutput.zipWithIndex.map {
+              case (attr, i) =>
+                val getStructField = GetStructField(unnestOutput, i, 
Some(attr.name))
+                val caseWhen = CaseWhen(
+                  Seq((isNullOrEmpty, Literal(null, getStructField.dataType))),
+                  getStructField
+                )
+                Alias(caseWhen, generatePostAliasName)(attr.exprId, 
attr.qualifier)
+            }
+            ProjectExec(generate.requiredChildOutput ++ newOutput, newGenerate)
+          } else {
+            val newGenerate = generate.copy(generatorOutput = 
Seq(unnestOutput))
+            val newOutput = generate.generatorOutput.zipWithIndex.map {
+              case (attr, i) =>
+                val getStructField = GetStructField(unnestOutput, i, 
Some(attr.name))
+                Alias(getStructField, generatePostAliasName)(attr.exprId, 
attr.qualifier)
+            }
+            ProjectExec(generate.requiredChildOutput ++ newOutput, newGenerate)
+          }
+        case Explode(_) if generate.outer =>
+          // Drop the last column of generatorOutput, which is the boolean 
representing whether
+          // the null value is unnested from the input array/map (e.g. 
array(1, null)), or the
+          // array/map itself is null or empty (e.g. array(), map(), null).
+          val isNullOrEmpty =
+            AttributeReference(generatePostAliasName, BooleanType, nullable = 
true)()
+          val newGenerate =
+            generate.copy(generatorOutput = generate.generatorOutput :+ 
isNullOrEmpty)
+          val newOutput = generate.generatorOutput.map {
+            attr =>
+              val caseWhen = CaseWhen(
+                Seq((isNullOrEmpty, Literal(null, attr.dataType))),
+                attr
+              )
+              Alias(caseWhen, generatePostAliasName)(attr.exprId, 
attr.qualifier)
           }
           ProjectExec(generate.requiredChildOutput ++ newOutput, newGenerate)
         case _ => generate
diff --git 
a/backends-velox/src/test/scala/org/apache/gluten/execution/MiscOperatorSuite.scala
 
b/backends-velox/src/test/scala/org/apache/gluten/execution/MiscOperatorSuite.scala
index 33b7f140fb..333267e838 100644
--- 
a/backends-velox/src/test/scala/org/apache/gluten/execution/MiscOperatorSuite.scala
+++ 
b/backends-velox/src/test/scala/org/apache/gluten/execution/MiscOperatorSuite.scala
@@ -930,81 +930,98 @@ class MiscOperatorSuite extends 
VeloxWholeStageTransformerSuite with AdaptiveSpa
 
   test("test explode/posexplode function") {
     Seq("explode", "posexplode").foreach {
-      func =>
-        // Literal: func(literal)
-        runQueryAndCompare(s"""
-                              |SELECT $func(array(1, 2, 3));
-                              |""".stripMargin) {
-          checkGlutenOperatorMatch[GenerateExecTransformer]
-        }
-        runQueryAndCompare(s"""
-                              |SELECT $func(map(1, 'a', 2, 'b'));
-                              |""".stripMargin) {
-          checkGlutenOperatorMatch[GenerateExecTransformer]
-        }
-        runQueryAndCompare(
-          s"""
-             |SELECT $func(array(map(1, 'a', 2, 'b'), map(3, 'c', 4, 'd'), 
map(5, 'e', 6, 'f')));
-             |""".stripMargin) {
-          checkGlutenOperatorMatch[GenerateExecTransformer]
-        }
-        runQueryAndCompare(s"""
-                              |SELECT $func(map(1, array(1, 2), 2, array(3, 
4)));
-                              |""".stripMargin) {
-          checkGlutenOperatorMatch[GenerateExecTransformer]
-        }
+      f =>
+        Seq(true, false).foreach {
+          isOuter =>
+            val func = if (isOuter) s"${f}_outer" else f
+            // Literal: func(literal)
+            runQueryAndCompare(s"""
+                                  |SELECT $func(array(1, 2, 3));
+                                  |""".stripMargin) {
+              checkGlutenOperatorMatch[GenerateExecTransformer]
+            }
+            runQueryAndCompare(s"""
+                                  |SELECT $func(map(1, 'a', 2, 'b'));
+                                  |""".stripMargin) {
+              checkGlutenOperatorMatch[GenerateExecTransformer]
+            }
+            runQueryAndCompare(
+              s"""
+                 |SELECT
+                 |  $func(array(map(1, 'a', 2, 'b'), map(3, 'c', 4, 'd'), 
map(5, '', 6, null)));
+                 |""".stripMargin) {
+              checkGlutenOperatorMatch[GenerateExecTransformer]
+            }
+            runQueryAndCompare(s"""
+                                  |SELECT $func(map(1, array(1, 2), 2, 
array(3, 4), 3, array()));
+                                  |""".stripMargin) {
+              checkGlutenOperatorMatch[GenerateExecTransformer]
+            }
 
-        // CreateArray/CreateMap: func(array(col)), func(map(k, v))
-        withTempView("t1") {
-          sql("""select * from values (1), (2), (3), (4)
-                |as tbl(a)
+            // CreateArray/CreateMap: func(array(col)), func(map(k, v))
+            withTempView("t1") {
+              sql("""select * from values (1), (2), (3), (4), (null)
+                    |as tbl(a)
          """.stripMargin).createOrReplaceTempView("t1")
-          runQueryAndCompare(s"""
-                                |SELECT $func(array(a)) from t1;
-                                |""".stripMargin) {
-            checkGlutenOperatorMatch[GenerateExecTransformer]
-          }
-          sql("""select * from values (1, 'a'), (2, 'b'), (3, null), (4, null)
-                |as tbl(a, b)
+              runQueryAndCompare(s"""
+                                    |SELECT $func(array(a)) from t1;
+                                    |""".stripMargin) {
+                checkGlutenOperatorMatch[GenerateExecTransformer]
+              }
+              sql("""select * from values (1, 'a'), (2, 'b'), (3, null), (4, 
null)
+                    |as tbl(a, b)
          """.stripMargin).createOrReplaceTempView("t1")
-          runQueryAndCompare(s"""
-                                |SELECT $func(map(a, b)) from t1;
-                                |""".stripMargin) {
-            checkGlutenOperatorMatch[GenerateExecTransformer]
-          }
-        }
+              runQueryAndCompare(s"""
+                                    |SELECT $func(map(a, b)) from t1;
+                                    |""".stripMargin) {
+                checkGlutenOperatorMatch[GenerateExecTransformer]
+              }
+            }
 
-        // AttributeReference: func(col)
-        withTempView("t2") {
-          sql("""select * from values
-                |  array(1, 2, 3),
-                |  array(4, null)
-                |as tbl(a)
+            // AttributeReference: func(col)
+            withTempView("t2") {
+              sql("""select * from values
+                    |  array(1, 2, 3),
+                    |  array(4, null),
+                    |  array(),
+                    |  null
+                    |as tbl(a)
          """.stripMargin).createOrReplaceTempView("t2")
-          runQueryAndCompare(s"""
-                                |SELECT $func(a) from t2;
-                                |""".stripMargin) {
-            // No ProjectExecTransformer is introduced.
-            checkSparkOperatorChainMatch[GenerateExecTransformer, 
FilterExecTransformer]
-          }
-          sql("""select * from values
-                |  map(1, 'a', 2, 'b', 3, null),
-                |  map(4, null)
-                |as tbl(a)
+              runQueryAndCompare(s"""
+                                    |SELECT $func(a) from t2;
+                                    |""".stripMargin) {
+                df =>
+                  if (!isOuter) {
+                    // No ProjectExecTransformer is introduced.
+                    checkSparkOperatorChainMatch[GenerateExecTransformer, 
FilterExecTransformer](df)
+                  }
+                  checkGlutenOperatorMatch[GenerateExecTransformer](df)
+              }
+              sql("""select * from values
+                    |  map(1, 'a', 2, 'b', 3, null),
+                    |  map(4, null),
+                    |  map(),
+                    |  null
+                    |as tbl(a)
          """.stripMargin).createOrReplaceTempView("t2")
-          runQueryAndCompare(s"""
-                                |SELECT $func(a) from t2;
-                                |""".stripMargin) {
-            // No ProjectExecTransformer is introduced.
-            checkSparkOperatorChainMatch[GenerateExecTransformer, 
FilterExecTransformer]
-          }
+              runQueryAndCompare(s"""
+                                    |SELECT $func(a) from t2;
+                                    |""".stripMargin) {
+                df =>
+                  if (!isOuter) {
+                    // No ProjectExecTransformer is introduced.
+                    checkSparkOperatorChainMatch[GenerateExecTransformer, 
FilterExecTransformer](df)
+                  }
+                  checkGlutenOperatorMatch[GenerateExecTransformer](df)
+              }
 
-          runQueryAndCompare(
-            s"""
-               |SELECT 
$func(${VeloxDummyExpression.VELOX_DUMMY_EXPRESSION}(a)) from t2;
-               |""".stripMargin) {
-            checkGlutenOperatorMatch[GenerateExecTransformer]
-          }
+              runQueryAndCompare(
+                s"""
+                   |SELECT 
$func(${VeloxDummyExpression.VELOX_DUMMY_EXPRESSION}(a)) from t2;
+                   |""".stripMargin) {
+                checkGlutenOperatorMatch[GenerateExecTransformer]
+              }
+            }
         }
     }
   }
@@ -1047,58 +1064,67 @@ class MiscOperatorSuite extends 
VeloxWholeStageTransformerSuite with AdaptiveSpa
   }
 
   test("test inline function") {
-    // Literal: func(literal)
-    runQueryAndCompare(s"""
-                          |SELECT inline(array(
-                          |  named_struct('c1', 0, 'c2', 1),
-                          |  named_struct('c1', 2, 'c2', null)));
-                          |""".stripMargin) {
-      checkGlutenOperatorMatch[GenerateExecTransformer]
-    }
+    Seq(true, false).foreach {
+      isOuter =>
+        val func = if (isOuter) "inline_outer" else "inline"
 
-    // CreateArray: func(array(col))
-    withTempView("t1") {
-      sql("""SELECT * from values
-            |  (named_struct('c1', 0, 'c2', 1)),
-            |  (named_struct('c1', 2, 'c2', null)),
-            |  (null)
-            |as tbl(a)
+        // Literal: func(literal)
+        runQueryAndCompare(s"""
+                              |SELECT $func(array(
+                              |  named_struct('c1', 0, 'c2', 1),
+                              |  named_struct('c1', 2, 'c2', null)));
+                              |""".stripMargin) {
+          checkGlutenOperatorMatch[GenerateExecTransformer]
+        }
+
+        // CreateArray: func(array(col))
+        withTempView("t1") {
+          sql("""SELECT * from values
+                |  (named_struct('c1', 0, 'c2', 1)),
+                |  (named_struct('c1', 2, 'c2', null)),
+                |  (null)
+                |as tbl(a)
          """.stripMargin).createOrReplaceTempView("t1")
-      runQueryAndCompare(s"""
-                            |SELECT inline(array(a)) from t1;
-                            |""".stripMargin) {
-        checkGlutenOperatorMatch[GenerateExecTransformer]
-      }
-    }
+          runQueryAndCompare(s"""
+                                |SELECT $func(array(a)) from t1;
+                                |""".stripMargin) {
+            checkGlutenOperatorMatch[GenerateExecTransformer]
+          }
+        }
 
-    withTempView("t2") {
-      sql("""SELECT * from values
-            |  array(
-            |    named_struct('c1', 0, 'c2', 1),
-            |    null,
-            |    named_struct('c1', 2, 'c2', 3)
-            |  ),
-            |  array(
-            |    null,
-            |    named_struct('c1', 0, 'c2', 1),
-            |    named_struct('c1', 2, 'c2', 3)
-            |  )
-            |as tbl(a)
+        withTempView("t2") {
+          sql("""SELECT * from values
+                |  array(
+                |    named_struct('c1', 0, 'c2', 1),
+                |    null,
+                |    named_struct('c1', 2, 'c2', 3)
+                |  ),
+                |  array(
+                |    null,
+                |    named_struct('c1', 0, 'c2', 1),
+                |    named_struct('c1', 2, 'c2', 3)
+                |  ),
+                |  array(),
+                |  null
+                |as tbl(a)
          """.stripMargin).createOrReplaceTempView("t2")
-      runQueryAndCompare("""
-                           |SELECT inline(a) from t2;
-                           |""".stripMargin) {
-        checkGlutenOperatorMatch[GenerateExecTransformer]
-      }
-    }
+          runQueryAndCompare(s"""
+                                |SELECT $func(a) from t2;
+                                |""".stripMargin) {
+            checkGlutenOperatorMatch[GenerateExecTransformer]
+          }
+        }
 
-    // Fallback for array(struct(...), null) literal.
-    runQueryAndCompare(s"""
-                          |SELECT inline(array(
-                          |  named_struct('c1', 0, 'c2', 1),
-                          |  named_struct('c1', 2, 'c2', null),
-                          |  null));
-                          |""".stripMargin)(_)
+        // Fallback for array(struct(...), null) literal.
+        runQueryAndCompare(s"""
+                              |SELECT $func(array(
+                              |  named_struct('c1', 0, 'c2', 1),
+                              |  named_struct('c1', 2, 'c2', null),
+                              |  null));
+                              |""".stripMargin) {
+          checkSparkOperatorMatch[GenerateExec]
+        }
+    }
   }
 
   test("test multi-generate") {
diff --git a/cpp/velox/substrait/SubstraitToVeloxPlan.cc 
b/cpp/velox/substrait/SubstraitToVeloxPlan.cc
index 2fe4b14a64..53f5b7b607 100644
--- a/cpp/velox/substrait/SubstraitToVeloxPlan.cc
+++ b/cpp/velox/substrait/SubstraitToVeloxPlan.cc
@@ -876,13 +876,15 @@ core::PlanNodePtr 
SubstraitToVeloxPlanConverter::toVeloxPlan(const ::substrait::
   }
 
   std::optional<std::string> ordinalityName = std::nullopt;
-  if (generateRel.has_advanced_extension() &&
-      
SubstraitParser::configSetInOptimization(generateRel.advanced_extension(), 
"isPosExplode=")) {
-    ordinalityName = std::make_optional<std::string>("pos");
-  }
-
-  // TODO: allow to set this in SQL
   std::optional<std::string> emptyUnnestValueName = std::nullopt;
+  if (generateRel.has_advanced_extension()) {
+    if 
(SubstraitParser::configSetInOptimization(generateRel.advanced_extension(), 
"isPosExplode=")) {
+      ordinalityName = std::make_optional<std::string>("pos");
+    }
+    if 
(SubstraitParser::configSetInOptimization(generateRel.advanced_extension(), 
"isOuter=")) {
+      emptyUnnestValueName = std::make_optional<std::string>("empty_unnest");
+    }
+  }
 
   return std::make_shared<core::UnnestNode>(
       nextPlanNodeId(), replicated, unnest, std::move(unnestNames), 
ordinalityName, emptyUnnestValueName, childNode);
diff --git 
a/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
 
b/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
index 91dabb92a9..2344316242 100644
--- 
a/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
+++ 
b/gluten-ut/spark32/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
@@ -230,6 +230,7 @@ class VeloxTestSettings extends BackendTestSettings {
     .excludeGlutenTest("from_unixtime")
   enableSuite[GlutenDecimalExpressionSuite]
   enableSuite[GlutenDecimalPrecisionSuite]
+  enableSuite[GlutenGeneratorExpressionSuite]
   enableSuite[GlutenStringFunctionsSuite]
   enableSuite[GlutenRegexpExpressionsSuite]
   enableSuite[GlutenNullExpressionsSuite]
diff --git 
a/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
 
b/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
new file mode 100644
index 0000000000..d1867936c1
--- /dev/null
+++ 
b/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.spark.sql.catalyst.expressions
+
+import org.apache.spark.sql.GlutenTestsTrait
+
+class GlutenGeneratorExpressionSuite extends GeneratorExpressionSuite with 
GlutenTestsTrait {}
diff --git 
a/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
 
b/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
index ceeaaa1de8..dd0121393b 100644
--- 
a/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
+++ 
b/gluten-ut/spark33/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
@@ -150,6 +150,7 @@ class VeloxTestSettings extends BackendTestSettings {
   enableSuite[GlutenDecimalPrecisionSuite]
   enableSuite[GlutenHashExpressionsSuite]
   enableSuite[GlutenHigherOrderFunctionsSuite]
+  enableSuite[GlutenGeneratorExpressionSuite]
   enableSuite[GlutenIntervalExpressionsSuite]
   enableSuite[GlutenJsonExpressionsSuite]
     // https://github.com/apache/incubator-gluten/issues/8102
diff --git 
a/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
 
b/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
new file mode 100644
index 0000000000..d1867936c1
--- /dev/null
+++ 
b/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.spark.sql.catalyst.expressions
+
+import org.apache.spark.sql.GlutenTestsTrait
+
+class GlutenGeneratorExpressionSuite extends GeneratorExpressionSuite with 
GlutenTestsTrait {}
diff --git 
a/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
 
b/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
index 47e8935cfa..82ba127334 100644
--- 
a/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
+++ 
b/gluten-ut/spark34/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
@@ -143,6 +143,7 @@ class VeloxTestSettings extends BackendTestSettings {
     .excludeGlutenTest("from_unixtime")
   enableSuite[GlutenDecimalExpressionSuite]
   enableSuite[GlutenDecimalPrecisionSuite]
+  enableSuite[GlutenGeneratorExpressionSuite]
   enableSuite[GlutenHashExpressionsSuite]
   enableSuite[GlutenHigherOrderFunctionsSuite]
   enableSuite[GlutenIntervalExpressionsSuite]
diff --git 
a/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
 
b/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
new file mode 100644
index 0000000000..d1867936c1
--- /dev/null
+++ 
b/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.spark.sql.catalyst.expressions
+
+import org.apache.spark.sql.GlutenTestsTrait
+
+class GlutenGeneratorExpressionSuite extends GeneratorExpressionSuite with 
GlutenTestsTrait {}
diff --git 
a/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
 
b/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
index 23c89362d5..90a731c9d4 100644
--- 
a/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
+++ 
b/gluten-ut/spark35/src/test/scala/org/apache/gluten/utils/velox/VeloxTestSettings.scala
@@ -143,6 +143,7 @@ class VeloxTestSettings extends BackendTestSettings {
     .excludeGlutenTest("from_unixtime")
   enableSuite[GlutenDecimalExpressionSuite]
   enableSuite[GlutenDecimalPrecisionSuite]
+  enableSuite[GlutenGeneratorExpressionSuite]
   enableSuite[GlutenHashExpressionsSuite]
   enableSuite[GlutenHigherOrderFunctionsSuite]
   enableSuite[GlutenIntervalExpressionsSuite]
diff --git 
a/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
 
b/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
new file mode 100644
index 0000000000..d1867936c1
--- /dev/null
+++ 
b/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/catalyst/expressions/GlutenGeneratorExpressionSuite.scala
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.spark.sql.catalyst.expressions
+
+import org.apache.spark.sql.GlutenTestsTrait
+
+class GlutenGeneratorExpressionSuite extends GeneratorExpressionSuite with 
GlutenTestsTrait {}


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

Reply via email to