diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/QueryPlan.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/QueryPlan.scala index 125181fb213f..5a17c93c71f4 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/QueryPlan.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/QueryPlan.scala @@ -21,6 +21,7 @@ import org.apache.spark.sql.catalyst.expressions._ import org.apache.spark.sql.catalyst.trees.{CurrentOrigin, TreeNode} import org.apache.spark.sql.internal.SQLConf import org.apache.spark.sql.types.{DataType, StructType} +import org.apache.spark.sql.AnalysisException abstract class QueryPlan[PlanType <: QueryPlan[PlanType]] extends TreeNode[PlanType] { self: PlanType => @@ -267,6 +268,21 @@ abstract class QueryPlan[PlanType <: QueryPlan[PlanType]] extends TreeNode[PlanT * All the attributes that are used for this plan. */ lazy val allAttributes: AttributeSeq = children.flatMap(_.output) + + /** + * Converts the query plan to string and appends it via provided function. + */ + def appendOrError( + append: String => Unit, + verbose: Boolean, + addSuffix: Boolean, + maxFields: Int = SQLConf.get.maxToStringFields): Unit = { + try { + treeString(append, verbose, addSuffix, maxFields) + } catch { + case e: AnalysisException => append(e.toString) + } + } } object QueryPlan extends PredicateHelper { diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/QueryExecution.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/QueryExecution.scala index 8d1c7f60db6f..89f10fcdb76c 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/QueryExecution.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/QueryExecution.scala @@ -196,38 +196,31 @@ class QueryExecution( val rope = new StringRope() rope.append("== Physical Plan ==\n") - appendOrError(rope.append)( - executedPlan.treeString(_, false, false, SQLConf.get.maxToStringFields)) + executedPlan.appendOrError(rope.append, verbose = false, addSuffix = false) rope.append("\n") rope.toString } - private def appendOrError(append: String => Unit)(f: (String => Unit) => Unit): Unit = { - try f(append) - catch { - case e: AnalysisException => append(e.toString) - } - } - private def writePlans(append: String => Unit, maxFields: Int): Unit = { - def stringOrError[A](f: => A): String = { - try f.toString catch { case e: AnalysisException => e.toString } - } val (verbose, addSuffix) = (true, false) append("== Parsed Logical Plan ==\n") - appendOrError(append)(logical.treeString(_, verbose, addSuffix, maxFields)) + logical.appendOrError(append, verbose, addSuffix, maxFields) append("\n== Analyzed Logical Plan ==\n") - val analyzedOutput = stringOrError(truncatedString( - analyzed.output.map(o => s"${o.name}: ${o.dataType.simpleString}"), ", ", maxFields)) + val analyzedOutput = try { + truncatedString( + analyzed.output.map(o => s"${o.name}: ${o.dataType.simpleString}"), ", ", maxFields) + } catch { + case e: AnalysisException => e.toString + } append(analyzedOutput) append("\n") - appendOrError(append)(analyzed.treeString(_, verbose, addSuffix, maxFields)) + analyzed.appendOrError(append, verbose, addSuffix, maxFields) append("\n== Optimized Logical Plan ==\n") - appendOrError(append)(optimizedPlan.treeString(_, verbose, addSuffix, maxFields)) + optimizedPlan.appendOrError(append, verbose, addSuffix, maxFields) append("\n== Physical Plan ==\n") - appendOrError(append)(executedPlan.treeString(_, verbose, addSuffix, maxFields)) + executedPlan.appendOrError(append, verbose, addSuffix, maxFields) } override def toString: String = withRedaction { @@ -239,16 +232,15 @@ class QueryExecution( def stringWithStats: String = withRedaction { val rope = new StringRope() - val maxFields = SQLConf.get.maxToStringFields // trigger to compute stats for logical plans optimizedPlan.stats // only show optimized logical plan and physical plan rope.append("== Optimized Logical Plan ==\n") - appendOrError(rope.append)(optimizedPlan.treeString(_, true, true, maxFields)) + optimizedPlan.appendOrError(rope.append, verbose = true, addSuffix = true) rope.append("\n== Physical Plan ==\n") - appendOrError(rope.append)(executedPlan.treeString(_, true, false, maxFields)) + executedPlan.appendOrError(rope.append, verbose = true, addSuffix = false) rope.append("\n") rope.toString