Skip to content

Commit 6abc4a1

Browse files
committed
[SPARK-45841][SQL] Expose stack trace by DataFrameQueryContext
### What changes were proposed in this pull request? In the PR, I propose to change the case class `DataFrameQueryContext`, and add stack traces as a field and override `callSite`, `fragment` using the new field `stackTrace`. ### Why are the changes needed? By exposing the stack trace, we give users opportunity to see all stack traces needed for debugging. ### Does this PR introduce _any_ user-facing change? No, `DataFrameQueryContext` hasn't been released yet. ### How was this patch tested? By running the modified test suite: ``` $ build/sbt "test:testOnly *DatasetSuite" ``` ### Was this patch authored or co-authored using generative AI tooling? No. Closes #43703 from MaxGekk/stack-traces-in-DataFrameQueryContext. Authored-by: Max Gekk <[email protected]> Signed-off-by: Max Gekk <[email protected]>
1 parent f866549 commit 6abc4a1

File tree

2 files changed

+22
-24
lines changed

2 files changed

+22
-24
lines changed

sql/api/src/main/scala/org/apache/spark/sql/catalyst/trees/QueryContexts.scala

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,27 @@ case class SQLQueryContext(
134134
override def callSite: String = throw new UnsupportedOperationException
135135
}
136136

137-
case class DataFrameQueryContext(
138-
override val fragment: String,
139-
override val callSite: String) extends QueryContext {
137+
case class DataFrameQueryContext(stackTrace: Seq[StackTraceElement]) extends QueryContext {
140138
override val contextType = QueryContextType.DataFrame
141139

142140
override def objectType: String = throw new UnsupportedOperationException
143141
override def objectName: String = throw new UnsupportedOperationException
144142
override def startIndex: Int = throw new UnsupportedOperationException
145143
override def stopIndex: Int = throw new UnsupportedOperationException
146144

145+
override val fragment: String = {
146+
stackTrace.headOption.map { firstElem =>
147+
val methodName = firstElem.getMethodName
148+
if (methodName.length > 1 && methodName(0) == '$') {
149+
methodName.substring(1)
150+
} else {
151+
methodName
152+
}
153+
}.getOrElse("")
154+
}
155+
156+
override val callSite: String = stackTrace.tail.headOption.map(_.toString).getOrElse("")
157+
147158
override lazy val summary: String = {
148159
val builder = new StringBuilder
149160
builder ++= "== DataFrame ==\n"
@@ -157,19 +168,3 @@ case class DataFrameQueryContext(
157168
builder.result()
158169
}
159170
}
160-
161-
object DataFrameQueryContext {
162-
def apply(elements: Array[StackTraceElement]): DataFrameQueryContext = {
163-
val fragment = elements.headOption.map { firstElem =>
164-
val methodName = firstElem.getMethodName
165-
if (methodName.length > 1 && methodName(0) == '$') {
166-
methodName.substring(1)
167-
} else {
168-
methodName
169-
}
170-
}.getOrElse("")
171-
val callSite = elements.tail.headOption.map(_.toString).getOrElse("")
172-
173-
DataFrameQueryContext(fragment, callSite)
174-
}
175-
}

sql/core/src/test/scala/org/apache/spark/sql/DatasetSuite.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import org.apache.spark.sql.catalyst.encoders.{AgnosticEncoders, ExpressionEncod
3737
import org.apache.spark.sql.catalyst.encoders.AgnosticEncoders.BoxedIntEncoder
3838
import org.apache.spark.sql.catalyst.expressions.{CodegenObjectFactoryMode, GenericRowWithSchema}
3939
import org.apache.spark.sql.catalyst.plans.{LeftAnti, LeftSemi}
40+
import org.apache.spark.sql.catalyst.trees.DataFrameQueryContext
4041
import org.apache.spark.sql.catalyst.util.sideBySide
4142
import org.apache.spark.sql.execution.{LogicalRDD, RDDScanExec, SQLExecution}
4243
import org.apache.spark.sql.execution.adaptive.AdaptiveSparkPlanHelper
@@ -2668,16 +2669,18 @@ class DatasetSuite extends QueryTest
26682669
withSQLConf(SQLConf.ANSI_ENABLED.key -> "true") {
26692670
val df = Seq(1).toDS()
26702671
var callSitePattern: String = null
2672+
val exception = intercept[AnalysisException] {
2673+
callSitePattern = getNextLineCallSitePattern()
2674+
val c = col("a")
2675+
df.select(c)
2676+
}
26712677
checkError(
2672-
exception = intercept[AnalysisException] {
2673-
callSitePattern = getNextLineCallSitePattern()
2674-
val c = col("a")
2675-
df.select(c)
2676-
},
2678+
exception,
26772679
errorClass = "UNRESOLVED_COLUMN.WITH_SUGGESTION",
26782680
sqlState = "42703",
26792681
parameters = Map("objectName" -> "`a`", "proposal" -> "`value`"),
26802682
context = ExpectedContext(fragment = "col", callSitePattern = callSitePattern))
2683+
assert(exception.context.head.asInstanceOf[DataFrameQueryContext].stackTrace.length == 2)
26812684
}
26822685
}
26832686
}

0 commit comments

Comments
 (0)