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

dongjoon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 15ea9de88b8d [SPARK-47503][SQL] Make `makeDotNode` escape graph node 
name always
15ea9de88b8d is described below

commit 15ea9de88b8d8a87daa6abbc8e80c439e2d38e03
Author: Alexey <alexey13>
AuthorDate: Sun Mar 24 00:16:05 2024 -0700

    [SPARK-47503][SQL] Make `makeDotNode` escape graph node name always
    
    ### What changes were proposed in this pull request?
    To prevent corruption of dot file a node name should be escaped even if 
there is no metrics to display
    
    ### Why are the changes needed?
    This pr fixes a bug in spark history server which fails to display query 
for cached JDBC relation named in quotes.
    
    ### Does this PR introduce any user-facing change?
    No.
    
    ### How was this patch tested?
    Unit test.
    
    ### Was this patch authored or co-authored using generative AI tooling?
     No.
    
    Closes #45640 from alex35736/SPARK-47503.
    
    Lead-authored-by: Alexey <alexey13>
    Co-authored-by: Dongjoon Hyun <[email protected]>
    Signed-off-by: Dongjoon Hyun <[email protected]>
---
 .../spark/sql/execution/ui/SparkPlanGraph.scala    |  2 +-
 .../sql/execution/ui/SparkPlanGraphSuite.scala     | 46 ++++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/SparkPlanGraph.scala
 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/SparkPlanGraph.scala
index 11ba3cd05e26..f94d7dc7ab4c 100644
--- 
a/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/SparkPlanGraph.scala
+++ 
b/sql/core/src/main/scala/org/apache/spark/sql/execution/ui/SparkPlanGraph.scala
@@ -189,7 +189,7 @@ class SparkPlanGraphNode(
     } else {
       // SPARK-30684: when there is no metrics, add empty lines to increase 
the height of the node,
       // so that there won't be gaps between an edge and a small node.
-      s"<br><b>$name</b><br><br>"
+      s"<br><b>${StringEscapeUtils.escapeJava(name)}</b><br><br>"
     }
     s"""  $id [id="$nodeId" labelType="html" label="$labelStr" 
tooltip="$tooltip"];"""
 
diff --git 
a/sql/core/src/test/scala/org/apache/spark/sql/execution/ui/SparkPlanGraphSuite.scala
 
b/sql/core/src/test/scala/org/apache/spark/sql/execution/ui/SparkPlanGraphSuite.scala
new file mode 100644
index 000000000000..975dbc1a1d8d
--- /dev/null
+++ 
b/sql/core/src/test/scala/org/apache/spark/sql/execution/ui/SparkPlanGraphSuite.scala
@@ -0,0 +1,46 @@
+/*
+ * 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.execution.ui
+
+import org.apache.spark.SparkFunSuite
+
+class SparkPlanGraphSuite extends SparkFunSuite {
+  test("SPARK-47503: name of a node should be escaped even if there is no 
metrics") {
+    val planGraphNode = new SparkPlanGraphNode(
+      id = 24,
+      name = "Scan JDBCRelation(\"test-schema\".tickets) [numPartitions=1]",
+      desc = "Scan JDBCRelation(\"test-schema\".tickets) [numPartitions=1] " +
+        "[ticket_no#0] PushedFilters: [], ReadSchema: 
struct<ticket_no:string>",
+      metrics = List(
+        SQLPlanMetric(
+          name = "number of output rows",
+          accumulatorId = 75,
+          metricType = "sum"
+        ),
+        SQLPlanMetric(
+          name = "JDBC query execution time",
+          accumulatorId = 35,
+          metricType = "nsTiming")))
+    val dotNode = planGraphNode.makeDotNode(Map.empty[Long, String])
+    val expectedDotNode = "  24 [id=\"node24\" labelType=\"html\" label=\"" +
+      "<br><b>Scan JDBCRelation(\\\"test-schema\\\".tickets) 
[numPartitions=1]</b><br><br>\" " +
+      "tooltip=\"Scan JDBCRelation(\\\"test-schema\\\".tickets) 
[numPartitions=1] [ticket_no#0] " +
+      "PushedFilters: [], ReadSchema: struct<ticket_no:string>\"];"
+
+    assertResult(expectedDotNode)(dotNode)
+  }
+}


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

Reply via email to