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

zhli 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 e975bf368 [VL] Enable map_zip_with, zip_with functions (#5610)
e975bf368 is described below

commit e975bf36881d031b8ef4e1b0c6eb5f1b675b895e
Author: Zhen Li <[email protected]>
AuthorDate: Wed May 8 10:34:21 2024 +0800

    [VL] Enable map_zip_with, zip_with functions (#5610)
    
    [VL] Enable map_zip_with, zip_with functions.
---
 .../org/apache/gluten/utils/CHExpressionUtil.scala |  2 ++
 .../execution/ScalarFunctionsValidateSuite.scala   | 37 ++++++++++++++++++++++
 docs/velox-backend-support-progress.md             |  3 +-
 .../gluten/expression/ExpressionMappings.scala     |  2 ++
 .../gluten/utils/velox/VeloxTestSettings.scala     |  2 ++
 .../spark/sql/GlutenDataFrameFunctionsSuite.scala  | 35 +++++++++++++++++++-
 .../gluten/utils/velox/VeloxTestSettings.scala     |  2 ++
 .../spark/sql/GlutenDataFrameFunctionsSuite.scala  | 35 +++++++++++++++++++-
 .../gluten/utils/velox/VeloxTestSettings.scala     |  2 ++
 .../spark/sql/GlutenDataFrameFunctionsSuite.scala  | 35 +++++++++++++++++++-
 .../gluten/utils/velox/VeloxTestSettings.scala     |  2 ++
 .../spark/sql/GlutenDataFrameFunctionsSuite.scala  | 35 +++++++++++++++++++-
 .../apache/gluten/expression/ExpressionNames.scala |  2 ++
 13 files changed, 189 insertions(+), 5 deletions(-)

diff --git 
a/backends-clickhouse/src/main/scala/org/apache/gluten/utils/CHExpressionUtil.scala
 
b/backends-clickhouse/src/main/scala/org/apache/gluten/utils/CHExpressionUtil.scala
index 0e645d039..b4190f1b8 100644
--- 
a/backends-clickhouse/src/main/scala/org/apache/gluten/utils/CHExpressionUtil.scala
+++ 
b/backends-clickhouse/src/main/scala/org/apache/gluten/utils/CHExpressionUtil.scala
@@ -186,6 +186,8 @@ object CHExpressionUtil {
     SKEWNESS -> DefaultValidator(),
     BIT_LENGTH -> DefaultValidator(),
     MAKE_YM_INTERVAL -> DefaultValidator(),
+    MAP_ZIP_WITH -> DefaultValidator(),
+    ZIP_WITH -> DefaultValidator(),
     KURTOSIS -> DefaultValidator(),
     REGR_R2 -> DefaultValidator(),
     REGR_SLOPE -> DefaultValidator(),
diff --git 
a/backends-velox/src/test/scala/org/apache/gluten/execution/ScalarFunctionsValidateSuite.scala
 
b/backends-velox/src/test/scala/org/apache/gluten/execution/ScalarFunctionsValidateSuite.scala
index 0a7a7d6cb..200c5f551 100644
--- 
a/backends-velox/src/test/scala/org/apache/gluten/execution/ScalarFunctionsValidateSuite.scala
+++ 
b/backends-velox/src/test/scala/org/apache/gluten/execution/ScalarFunctionsValidateSuite.scala
@@ -517,6 +517,43 @@ class ScalarFunctionsValidateSuite extends 
FunctionsValidateTest {
     }
   }
 
+  test("map_zip_with") {
+    withTempPath {
+      path =>
+        Seq((Map("a" -> 1, "b" -> 2), Map("a" -> 2, "b" -> 3)))
+          .toDF("m1", "m2")
+          .write
+          .parquet(path.getCanonicalPath)
+
+        
spark.read.parquet(path.getCanonicalPath).createOrReplaceTempView("map_tbl")
+
+        runQueryAndCompare(
+          "select map_zip_with(m1, m2, (k, v1, v2) -> k == v1 + v2) from 
map_tbl") {
+          checkGlutenOperatorMatch[ProjectExecTransformer]
+        }
+    }
+  }
+
+  test("zip_with") {
+    withTempPath {
+      path =>
+        Seq[(Seq[Integer], Seq[Integer])](
+          (Seq(9001, 9002, 9003), Seq(4, 5, 6)),
+          (Seq(1, 2), Seq(3, 4)),
+          (Seq.empty, Seq.empty),
+          (null, null)
+        ).toDF("val1", "val2")
+          .write
+          .parquet(path.getCanonicalPath)
+
+        
spark.read.parquet(path.getCanonicalPath).createOrReplaceTempView("array_tbl")
+
+        runQueryAndCompare("select zip_with(val1, val2, (x, y) -> x + y) from 
array_tbl") {
+          checkGlutenOperatorMatch[ProjectExecTransformer]
+        }
+    }
+  }
+
   test("Test isnan function") {
     runQueryAndCompare(
       "SELECT isnan(l_orderkey), isnan(cast('NaN' as double)), 
isnan(0.0F/0.0F)" +
diff --git a/docs/velox-backend-support-progress.md 
b/docs/velox-backend-support-progress.md
index e98587efb..1171b7d91 100644
--- a/docs/velox-backend-support-progress.md
+++ b/docs/velox-backend-support-progress.md
@@ -291,6 +291,7 @@ Gluten supports 199 functions. (Drag to right to see all 
data types)
 | map_from_entries              | map_from_entries       |                     
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | map_keys                      | map_keys               | map_keys            
  | S      |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | map_values                    | map_values             | map_values          
  | S      |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      | S   |        |     |
+| map_zip_with                    | map_zip_with             |             | S 
     |                          |         |      |       |     |      |       | 
       |      |           |        |         |      |        |          |       
| S   |        |     |
 | named_struct,struct           | row_construct          | named_struct        
  | S      |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     | S      |     |
 | posexplode_outer,posexplode   |                        |                     
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | sequence                      |                        |                     
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
@@ -302,7 +303,7 @@ Gluten supports 199 functions. (Drag to right to see all 
data types)
 | transform                     | transform              | transofrm           
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | transform_keys                | transform_keys         |                     
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | transform_values              | transform_values       |                     
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
-| zip_with                      | zip_with               |                     
  |        |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
+| zip_with                      | zip_with               |   S                 
   |        |                          |         |      |       |     |      |  
     |        |      |           |        |         |      |        |          
|       |     |        |     |
 | add_months                    |                        |                     
  | S      |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | current_date                  |                        |                     
  | S*     |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
 | current_timestamp             |                        |                     
  | S*     |                          |         |      |       |     |      |   
    |        |      |           |        |         |      |        |          | 
      |     |        |     |
diff --git 
a/gluten-core/src/main/scala/org/apache/gluten/expression/ExpressionMappings.scala
 
b/gluten-core/src/main/scala/org/apache/gluten/expression/ExpressionMappings.scala
index 920b6fab8..ef43c2724 100644
--- 
a/gluten-core/src/main/scala/org/apache/gluten/expression/ExpressionMappings.scala
+++ 
b/gluten-core/src/main/scala/org/apache/gluten/expression/ExpressionMappings.scala
@@ -240,6 +240,7 @@ object ExpressionMappings {
     Sig[ArrayForAll](FORALL),
     Sig[ArrayExists](EXISTS),
     Sig[Shuffle](SHUFFLE),
+    Sig[ZipWith](ZIP_WITH),
     // Map functions
     Sig[CreateMap](CREATE_MAP),
     Sig[GetMapValue](GET_MAP_VALUE),
@@ -247,6 +248,7 @@ object ExpressionMappings {
     Sig[MapValues](MAP_VALUES),
     Sig[MapFromArrays](MAP_FROM_ARRAYS),
     Sig[MapEntries](MAP_ENTRIES),
+    Sig[MapZipWith](MAP_ZIP_WITH),
     Sig[StringToMap](STR_TO_MAP),
     // Struct functions
     Sig[GetStructField](GET_STRUCT_FIELD),
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 4844b7351..b9f8c0665 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
@@ -278,6 +278,8 @@ class VeloxTestSettings extends BackendTestSettings {
     .exclude("shuffle function - array for primitive type not containing null")
     .exclude("shuffle function - array for primitive type containing null")
     .exclude("shuffle function - array for non-primitive type")
+    // Rewrite this test because Velox sorts rows by key for primitive data 
types, which disrupts the original row sequence.
+    .exclude("map_zip_with function - map of primitive types")
   enableSuite[GlutenDataFrameTungstenSuite]
   enableSuite[GlutenDataFrameSetOperationsSuite]
     // Result depends on the implementation for nondeterministic expression 
rand.
diff --git 
a/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
 
b/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
index 44981e1ce..2b0b40790 100644
--- 
a/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
+++ 
b/gluten-ut/spark32/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
@@ -16,4 +16,37 @@
  */
 package org.apache.spark.sql
 
-class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {}
+import org.apache.spark.sql.functions._
+
+class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {
+  import testImplicits._
+
+  testGluten("map_zip_with function - map of primitive types") {
+    val df = Seq(
+      (Map(8 -> 6L, 3 -> 5L, 6 -> 2L), Map[Integer, Integer]((6, 4), (8, 2), 
(3, 2))),
+      (Map(10 -> 6L, 8 -> 3L), Map[Integer, Integer]((8, 4), (4, null))),
+      (Map.empty[Int, Long], Map[Integer, Integer]((5, 1))),
+      (Map(5 -> 1L), null)
+    ).toDF("m1", "m2")
+
+    GlutenQueryTestUtil.sameRows(
+      df.selectExpr("map_zip_with(m1, m2, (k, v1, v2) -> k == v1 + 
v2)").collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+
+    GlutenQueryTestUtil.sameRows(
+      df.select(map_zip_with(df("m1"), df("m2"), (k, v1, v2) => k === v1 + 
v2)).collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+  }
+}
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 c6f6b0d33..642873028 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
@@ -943,6 +943,8 @@ class VeloxTestSettings extends BackendTestSettings {
     .exclude("shuffle function - array for primitive type not containing null")
     .exclude("shuffle function - array for primitive type containing null")
     .exclude("shuffle function - array for non-primitive type")
+    // Rewrite this test because Velox sorts rows by key for primitive data 
types, which disrupts the original row sequence.
+    .exclude("map_zip_with function - map of primitive types")
   enableSuite[GlutenDataFrameHintSuite]
   enableSuite[GlutenDataFrameImplicitsSuite]
   enableSuite[GlutenDataFrameJoinSuite]
diff --git 
a/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
 
b/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
index 44981e1ce..2b0b40790 100644
--- 
a/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
+++ 
b/gluten-ut/spark33/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
@@ -16,4 +16,37 @@
  */
 package org.apache.spark.sql
 
-class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {}
+import org.apache.spark.sql.functions._
+
+class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {
+  import testImplicits._
+
+  testGluten("map_zip_with function - map of primitive types") {
+    val df = Seq(
+      (Map(8 -> 6L, 3 -> 5L, 6 -> 2L), Map[Integer, Integer]((6, 4), (8, 2), 
(3, 2))),
+      (Map(10 -> 6L, 8 -> 3L), Map[Integer, Integer]((8, 4), (4, null))),
+      (Map.empty[Int, Long], Map[Integer, Integer]((5, 1))),
+      (Map(5 -> 1L), null)
+    ).toDF("m1", "m2")
+
+    GlutenQueryTestUtil.sameRows(
+      df.selectExpr("map_zip_with(m1, m2, (k, v1, v2) -> k == v1 + 
v2)").collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+
+    GlutenQueryTestUtil.sameRows(
+      df.select(map_zip_with(df("m1"), df("m2"), (k, v1, v2) => k === v1 + 
v2)).collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+  }
+}
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 033e084b8..a046f0a02 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
@@ -948,6 +948,8 @@ class VeloxTestSettings extends BackendTestSettings {
     .exclude("shuffle function - array for primitive type not containing null")
     .exclude("shuffle function - array for primitive type containing null")
     .exclude("shuffle function - array for non-primitive type")
+    // Rewrite this test because Velox sorts rows by key for primitive data 
types, which disrupts the original row sequence.
+    .exclude("map_zip_with function - map of primitive types")
   enableSuite[GlutenDataFrameHintSuite]
   enableSuite[GlutenDataFrameImplicitsSuite]
   enableSuite[GlutenDataFrameJoinSuite]
diff --git 
a/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
 
b/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
index 44981e1ce..2b0b40790 100644
--- 
a/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
+++ 
b/gluten-ut/spark34/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
@@ -16,4 +16,37 @@
  */
 package org.apache.spark.sql
 
-class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {}
+import org.apache.spark.sql.functions._
+
+class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {
+  import testImplicits._
+
+  testGluten("map_zip_with function - map of primitive types") {
+    val df = Seq(
+      (Map(8 -> 6L, 3 -> 5L, 6 -> 2L), Map[Integer, Integer]((6, 4), (8, 2), 
(3, 2))),
+      (Map(10 -> 6L, 8 -> 3L), Map[Integer, Integer]((8, 4), (4, null))),
+      (Map.empty[Int, Long], Map[Integer, Integer]((5, 1))),
+      (Map(5 -> 1L), null)
+    ).toDF("m1", "m2")
+
+    GlutenQueryTestUtil.sameRows(
+      df.selectExpr("map_zip_with(m1, m2, (k, v1, v2) -> k == v1 + 
v2)").collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+
+    GlutenQueryTestUtil.sameRows(
+      df.select(map_zip_with(df("m1"), df("m2"), (k, v1, v2) => k === v1 + 
v2)).collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+  }
+}
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 7c809ec6d..4583396b4 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
@@ -964,6 +964,8 @@ class VeloxTestSettings extends BackendTestSettings {
     .exclude("shuffle function - array for primitive type not containing null")
     .exclude("shuffle function - array for primitive type containing null")
     .exclude("shuffle function - array for non-primitive type")
+    // Rewrite this test because Velox sorts rows by key for primitive data 
types, which disrupts the original row sequence.
+    .exclude("map_zip_with function - map of primitive types")
   enableSuite[GlutenDataFrameHintSuite]
   enableSuite[GlutenDataFrameImplicitsSuite]
   enableSuite[GlutenDataFrameJoinSuite]
diff --git 
a/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
 
b/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
index 44981e1ce..2b0b40790 100644
--- 
a/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
+++ 
b/gluten-ut/spark35/src/test/scala/org/apache/spark/sql/GlutenDataFrameFunctionsSuite.scala
@@ -16,4 +16,37 @@
  */
 package org.apache.spark.sql
 
-class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {}
+import org.apache.spark.sql.functions._
+
+class GlutenDataFrameFunctionsSuite extends DataFrameFunctionsSuite with 
GlutenSQLTestsTrait {
+  import testImplicits._
+
+  testGluten("map_zip_with function - map of primitive types") {
+    val df = Seq(
+      (Map(8 -> 6L, 3 -> 5L, 6 -> 2L), Map[Integer, Integer]((6, 4), (8, 2), 
(3, 2))),
+      (Map(10 -> 6L, 8 -> 3L), Map[Integer, Integer]((8, 4), (4, null))),
+      (Map.empty[Int, Long], Map[Integer, Integer]((5, 1))),
+      (Map(5 -> 1L), null)
+    ).toDF("m1", "m2")
+
+    GlutenQueryTestUtil.sameRows(
+      df.selectExpr("map_zip_with(m1, m2, (k, v1, v2) -> k == v1 + 
v2)").collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+
+    GlutenQueryTestUtil.sameRows(
+      df.select(map_zip_with(df("m1"), df("m2"), (k, v1, v2) => k === v1 + 
v2)).collect.toSeq,
+      Seq(
+        Row(Map(8 -> true, 3 -> false, 6 -> true)),
+        Row(Map(10 -> null, 8 -> false, 4 -> null)),
+        Row(Map(5 -> null)),
+        Row(null)),
+      false
+    )
+  }
+}
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 2ad1c6f73..54a55b355 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
@@ -257,6 +257,7 @@ object ExpressionNames {
   final val EXISTS = "exists"
   final val TRANSFORM = "transform"
   final val SHUFFLE = "shuffle"
+  final val ZIP_WITH = "zip_with"
 
   // Map functions
   final val CREATE_MAP = "map"
@@ -265,6 +266,7 @@ object ExpressionNames {
   final val MAP_VALUES = "map_values"
   final val MAP_FROM_ARRAYS = "map_from_arrays"
   final val MAP_ENTRIES = "map_entries"
+  final val MAP_ZIP_WITH = "map_zip_with"
   final val STR_TO_MAP = "str_to_map"
 
   // struct functions


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

Reply via email to