Github user srowen commented on a diff in the pull request:
https://github.com/apache/spark/pull/22645#discussion_r223192945
--- Diff:
sql/core/src/main/scala/org/apache/spark/sql/execution/ui/AllExecutionsPage.scala
---
@@ -121,65 +122,242 @@ private[ui] class AllExecutionsPage(parent: SQLTab)
extends WebUIPage("") with L
{
if (running.nonEmpty) {
<li>
- <a href="#running-execution-table"><strong>Running
Queries:</strong></a>
+ <a href="#running"><strong>Running Queries:</strong></a>
{running.size}
</li>
}
}
{
if (completed.nonEmpty) {
<li>
- <a href="#completed-execution-table"><strong>Completed
Queries:</strong></a>
+ <a href="#completed"><strong>Completed
Queries:</strong></a>
{completed.size}
</li>
}
}
{
if (failed.nonEmpty) {
<li>
- <a href="#failed-execution-table"><strong>Failed
Queries:</strong></a>
+ <a href="#failed"><strong>Failed Queries:</strong></a>
{failed.size}
</li>
}
}
</ul>
</div>
+
UIUtils.headerSparkPage(request, "SQL", summary ++ content, parent,
Some(5000))
}
+
+ private def executionsTable(
+ request: HttpServletRequest,
+ executionTag: String,
+ executionData: Seq[SQLExecutionUIData],
+ currentTime: Long,
+ showRunningJobs: Boolean,
+ showSucceededJobs: Boolean,
+ showFailedJobs: Boolean): Seq[Node] = {
+
+ // stripXSS is called to remove suspicious characters used in XSS
attacks
+ val allParameters = request.getParameterMap.asScala.toMap.map { case
(k, v) =>
+ UIUtils.stripXSS(k) -> v.map(UIUtils.stripXSS).toSeq
+ }
+ val parameterOtherTable =
allParameters.filterNot(_._1.startsWith(executionTag))
+ .map(para => para._1 + "=" + para._2(0))
+
+ val parameterExecutionPage =
UIUtils.stripXSS(request.getParameter(s"$executionTag.page"))
+ val parameterExecutionSortColumn = UIUtils.stripXSS(request.
+ getParameter(s"$executionTag.sort"))
+ val parameterExecutionSortDesc =
UIUtils.stripXSS(request.getParameter(s"$executionTag.desc"))
+ val parameterExecutionPageSize = UIUtils.stripXSS(request.
+ getParameter(s"$executionTag.pageSize"))
+ val parameterExecutionPrevPageSize = UIUtils.stripXSS(request.
+ getParameter(s"$executionTag.prevPageSize"))
+
+ val executionPage =
Option(parameterExecutionPage).map(_.toInt).getOrElse(1)
+ val executionSortColumn = Option(parameterExecutionSortColumn).map {
sortColumn =>
+ UIUtils.decodeURLParameter(sortColumn)
+ }.getOrElse("ID")
+ val executionSortDesc =
Option(parameterExecutionSortDesc).map(_.toBoolean).getOrElse(
+ // New executions should be shown above old executions by default.
+ executionSortColumn == "ID"
+ )
+ val executionPageSize =
Option(parameterExecutionPageSize).map(_.toInt).getOrElse(100)
+ val executionPrevPageSize =
Option(parameterExecutionPrevPageSize).map(_.toInt).
+ getOrElse(executionPageSize)
+
+ // If the user has changed to a larger page size, then go to page 1 in
order to avoid
+ // IndexOutOfBoundsException.
+ val page: Int = if (executionPageSize <= executionPrevPageSize) {
+ executionPage
+ } else {
+ 1
+ }
+ val tableHeaderId = executionTag // "running", "completed" or "failed"
+
+ try {
+ new ExecutionPagedTable(
+ request,
+ parent,
+ executionData,
+ tableHeaderId,
+ executionTag,
+ UIUtils.prependBaseUri(request, parent.basePath),
+ "SQL", // subPath
+ parameterOtherTable,
+ currentTime,
+ pageSize = executionPageSize,
+ sortColumn = executionSortColumn,
+ desc = executionSortDesc,
+ showRunningJobs,
+ showSucceededJobs,
+ showFailedJobs).table(page)
+ } catch {
+ case e@(_: IllegalArgumentException | _: IndexOutOfBoundsException)
=>
+ <div class="alert alert-error">
+ <p>Error while rendering execution table:</p>
+ <pre>
+ {Utils.exceptionString(e)}
+ </pre>
+ </div>
+ }
+ }
}
-private[ui] abstract class ExecutionTable(
+
+private[ui] class ExecutionPagedTable(
+ request: HttpServletRequest,
parent: SQLTab,
- tableId: String,
+ data: Seq[SQLExecutionUIData],
+ tableHeaderId: String,
+ executionTag: String,
+ basePath: String,
+ subPath: String,
+ parameterOtherTable: Iterable[String],
currentTime: Long,
- executionUIDatas: Seq[SQLExecutionUIData],
+ pageSize: Int,
+ sortColumn: String,
+ desc: Boolean,
showRunningJobs: Boolean,
showSucceededJobs: Boolean,
- showFailedJobs: Boolean) {
+ showFailedJobs: Boolean) extends PagedTable[ExecutionTableRowData] {
+
+ override val dataSource = new ExecutionDataSource(
+ request,
+ parent,
+ data,
+ basePath,
+ currentTime,
+ pageSize,
+ sortColumn,
+ desc)
+
+ private val parameterPath =
s"$basePath/$subPath/?${parameterOtherTable.mkString("&")}"
- protected def baseHeader: Seq[String] = Seq(
- "ID",
- "Description",
- "Submitted",
- "Duration")
+ override def tableId: String = s"$executionTag-table"
- protected def header: Seq[String]
+ override def tableCssClass: String =
+ "table table-bordered table-condensed table-striped " +
+ "table-head-clickable table-cell-width-limited"
- protected def row(
- request: HttpServletRequest,
- currentTime: Long,
- executionUIData: SQLExecutionUIData): Seq[Node] = {
+ override def prevPageSizeFormField: String =
s"$executionTag.prevPageSize"
+
+ override def pageLink(page: Int): String = {
+ val encodedSortColumn = URLEncoder.encode(sortColumn, "UTF-8")
+ parameterPath +
+ s"&$pageNumberFormField=$page" +
+ s"&$executionTag.sort=$encodedSortColumn" +
+ s"&$executionTag.desc=$desc" +
+ s"&$pageSizeFormField=$pageSize" +
+ s"#$tableHeaderId"
+ }
+
+ override def pageSizeFormField: String = s"$executionTag.pageSize"
+
+ override def pageNumberFormField: String = s"$executionTag.page"
+
+ override def goButtonFormPath: String = {
+ val encodedSortColumn = URLEncoder.encode(sortColumn, "UTF-8")
+
s"$parameterPath&$executionTag.sort=$encodedSortColumn&$executionTag.desc=$desc#$tableHeaderId"
+ }
+
+ override def headers: Seq[Node] = {
+ // Information for each header: title, cssClass, and sortable
+ val executionHeadersAndCssClasses: Seq[(String, String, Boolean)] =
+ Seq(("ID", "", true), ("Description", "", true), ("Submitted", "",
true),
+ ("Duration", "", true)) ++ {
+ if (showRunningJobs && showSucceededJobs && showFailedJobs) {
+ Seq(("Running Job IDs", "", true), ("Succeeded Job IDs", "",
true),
+ ("Failed Job IDs", "", true))
+ } else if (showSucceededJobs && showFailedJobs) {
+ Seq(("Succeeded Job IDs", "", true), ("Failed Job IDs", "",
true))
+ }
+ else {
+ Seq(("Job IDs", "", true))
+ }
+ }
+
+ val sortableColumnHeaders = executionHeadersAndCssClasses.filter {
+ case (_, _, sortable) => sortable
+ }.map(header => header._1)
+
+ if(!sortableColumnHeaders.contains(sortColumn)) {
--- End diff --
Nit: space after if. Really, maybe just use `require`
---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]