diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/ExplainUtils.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/ExplainUtils.scala index ea6e1f933f..1eea0cd777 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/ExplainUtils.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/ExplainUtils.scala @@ -148,7 +148,7 @@ object ExplainUtils extends AdaptiveSparkPlanHelper { setOpId(p) case other: QueryPlan[_] => setOpId(other) - other.innerChildren.foldLeft(currentOperationID) { + currentOperationID = other.innerChildren.foldLeft(currentOperationID) { (curId, plan) => generateOperatorIDs(plan, curId) } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala index 52daa3d21b..aef39a24e9 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/ExplainSuite.scala @@ -677,6 +677,25 @@ class ExplainSuiteAE extends ExplainSuiteHelper with EnableAdaptiveExecutionSuit } } } + + test("SPARK-36795: Node IDs should not be duplicated when InMemoryRelation present") { + withTempView("t1", "t2") { + Seq(1).toDF("k").write.saveAsTable("t1") + Seq(1).toDF("key").write.saveAsTable("t2") + spark.sql("SELECT * FROM t1").persist() + val query = "SELECT * FROM (SELECT * FROM t1) join t2 " + + "ON k = t2.key" + val df = sql(query).toDF() + + val inMemoryRelationRegex = """InMemoryRelation \(([0-9]+)\)""".r + val columnarToRowRegex = """ColumnarToRow \(([0-9]+)\)""".r + val explainString = getNormalizedExplain(df, FormattedMode) + val inMemoryRelationNodeId = inMemoryRelationRegex.findAllIn(explainString).group(1) + val columnarToRowNodeId = columnarToRowRegex.findAllIn(explainString).group(1) + + assert(inMemoryRelationNodeId != columnarToRowNodeId) + } + } } case class ExplainSingleData(id: Int)