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

zhouyuan 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 192ff9a04d [VL] Offload str_to_map under the LAST_WIN map key dedup 
policy (#13462)
192ff9a04d is described below

commit 192ff9a04df1c2aaa473c672cf77a816bddc0db4
Author: Anshul Baliga <[email protected]>
AuthorDate: Thu Oct 29 14:23:06 2026 +0530

    [VL] Offload str_to_map under the LAST_WIN map key dedup policy (#13462)
---
 .../backendsapi/velox/VeloxSparkPlanExecApi.scala  | 19 -------------
 .../gluten/expression/ExpressionRestrictions.scala | 13 ---------
 .../functions/ScalarFunctionsValidateSuite.scala   | 32 ++++++++++++++++++++++
 3 files changed, 32 insertions(+), 32 deletions(-)

diff --git 
a/backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxSparkPlanExecApi.scala
 
b/backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxSparkPlanExecApi.scala
index a62fbf849c..4c64695507 100644
--- 
a/backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxSparkPlanExecApi.scala
+++ 
b/backends-velox/src/main/scala/org/apache/gluten/backendsapi/velox/VeloxSparkPlanExecApi.scala
@@ -1182,25 +1182,6 @@ class VeloxSparkPlanExecApi extends SparkPlanExecApi 
with Logging {
     }
   }
 
-  override def genStringToMapTransformer(
-      substraitExprName: String,
-      children: Seq[ExpressionTransformer],
-      expr: Expression): ExpressionTransformer = {
-    // Calling `.toString` on both sides ensures compatibility across all 
Spark versions.
-    // Starting from Spark 4.1, 
`SQLConf.get.getConf(SQLConf.MAP_KEY_DEDUP_POLICY)` returns
-    // an enum instead of a String.
-    if (
-      SQLConf.get.getConf(SQLConf.MAP_KEY_DEDUP_POLICY).toString
-        != SQLConf.MapKeyDedupPolicy.EXCEPTION.toString
-    ) {
-      GlutenExceptionUtil.throwsNotFullySupported(
-        ExpressionNames.STR_TO_MAP,
-        StrToMapRestrictions.ONLY_SUPPORT_MAP_KEY_DEDUP_POLICY
-      )
-    }
-    GenericExpressionTransformer(substraitExprName, children, expr)
-  }
-
   override def genFormatNumberTransformer(
       substraitExprName: String,
       children: Seq[ExpressionTransformer],
diff --git 
a/backends-velox/src/main/scala/org/apache/gluten/expression/ExpressionRestrictions.scala
 
b/backends-velox/src/main/scala/org/apache/gluten/expression/ExpressionRestrictions.scala
index b6bfd4119b..24b1aa6f8e 100644
--- 
a/backends-velox/src/main/scala/org/apache/gluten/expression/ExpressionRestrictions.scala
+++ 
b/backends-velox/src/main/scala/org/apache/gluten/expression/ExpressionRestrictions.scala
@@ -23,18 +23,6 @@ trait ExpressionRestrictions {
   val restrictionMessages: Array[String]
 }
 
-object StrToMapRestrictions extends ExpressionRestrictions {
-  val ONLY_SUPPORT_MAP_KEY_DEDUP_POLICY: String =
-    s"Only ${SQLConf.MAP_KEY_DEDUP_POLICY.key} = " +
-      s"${SQLConf.MapKeyDedupPolicy.EXCEPTION.toString} is supported for Velox 
backend"
-
-  override val functionName: String = ExpressionNames.STR_TO_MAP
-
-  override val restrictionMessages: Array[String] = Array(
-    ONLY_SUPPORT_MAP_KEY_DEDUP_POLICY
-  )
-}
-
 object FromJsonRestrictions extends ExpressionRestrictions {
   val MUST_ENABLE_PARTIAL_RESULTS: String =
     s"${ExpressionNames.FROM_JSON} with 'spark.sql.json.enablePartialResults = 
false' " +
@@ -120,7 +108,6 @@ object ExpressionRestrictions {
   // Called by gen-function-support-docs.py to get all restrictions.
   def listAllRestrictions(): Array[ExpressionRestrictions] = {
     Array(
-      StrToMapRestrictions,
       FromJsonRestrictions,
       ToJsonRestrictions,
       Unbase64Restrictions,
diff --git 
a/backends-velox/src/test/scala/org/apache/gluten/functions/ScalarFunctionsValidateSuite.scala
 
b/backends-velox/src/test/scala/org/apache/gluten/functions/ScalarFunctionsValidateSuite.scala
index c454db85a2..73a630492d 100644
--- 
a/backends-velox/src/test/scala/org/apache/gluten/functions/ScalarFunctionsValidateSuite.scala
+++ 
b/backends-velox/src/test/scala/org/apache/gluten/functions/ScalarFunctionsValidateSuite.scala
@@ -1811,4 +1811,36 @@ class ScalarFunctionsValidateSuite extends 
FunctionsValidateSuite {
         }
     }
   }
+
+  test("str_to_map with MAP_KEY_DEDUP_POLICY LAST_WIN") {
+    // Velox's str_to_map honors throw_exception_on_duplicate_map_keys, which 
Gluten derives
+    // from spark.sql.mapKeyDedupPolicy, so LAST_WIN no longer needs to fall 
back. Under
+    // LAST_WIN a repeated key keeps the position of its first occurrence and 
takes the last
+    // value. Entries without a key/value delimiter carry a NULL value and 
take part in
+    // deduplication as well.
+    withTempPath {
+      path =>
+        Seq("a:1,b:2,a:3", "x:10,x:20,x:30", "k,k", "k:1,k", "a:1,b:2,c:3")
+          .toDF("s")
+          .write
+          .parquet(path.getCanonicalPath)
+
+        
spark.read.parquet(path.getCanonicalPath).createOrReplaceTempView("str_to_map_tbl")
+
+        withSQLConf(
+          SQLConf.MAP_KEY_DEDUP_POLICY.key -> 
SQLConf.MapKeyDedupPolicy.LAST_WIN.toString) {
+          runQueryAndCompare("SELECT s, str_to_map(s, ',', ':') FROM 
str_to_map_tbl") {
+            checkGlutenPlan[ProjectExecTransformer]
+          }
+          runQueryAndCompare("SELECT s, str_to_map(s) FROM str_to_map_tbl") {
+            checkGlutenPlan[ProjectExecTransformer]
+          }
+          // Pin the entry order, which map equality ignores.
+          runQueryAndCompare(
+            "SELECT s, map_keys(str_to_map(s, ',', ':')) FROM str_to_map_tbl") 
{
+            checkGlutenPlan[ProjectExecTransformer]
+          }
+        }
+    }
+  }
 }


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

Reply via email to