diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowTablesJsonCommand.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowTablesJsonCommand.scala index 0dfc31705ae69..c52dc3de8fdd2 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowTablesJsonCommand.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/command/ShowTablesJsonCommand.scala @@ -107,30 +107,38 @@ case class ShowTablesJsonCommand( sparkSession: SparkSession, catalog: TableCatalog, ns: Seq[String]): JObject = { - val identifiers = if (!isExtended) { + val relations = if (!isExtended) { catalog match { case mc: RelationCatalog => - mc.listRelationSummaries(ns.toArray).map(_.identifier()) - case _ => catalog.listTables(ns.toArray) + mc.listRelationSummaries(ns.toArray).map(s => (s.identifier(), Option.empty[String])) + case _ => + catalog.listTables(ns.toArray).map(ident => (ident, Option.empty[String])) } } else { - catalog.listTables(ns.toArray) + catalog match { + case mc: RelationCatalog => + mc.listRelationSummaries(ns.toArray) + .map(s => (s.identifier(), Some(s.tableType()))) + case _ => + catalog.listTableSummaries(ns.toArray) + .map(s => (s.identifier(), Some(s.tableType()))) + } } val pat = pattern.getOrElse("*") - val filteredIdents = identifiers.filter { ident => + val filteredRelations = relations.filter { case (ident, _) => StringUtils.filterPattern(Seq(ident.name()), pat).nonEmpty } val jsonRows = new ArrayBuffer[JObject]() - filteredIdents.foreach { ident => + filteredRelations.foreach { case (ident, tableType) => val nsArray = JArray(ident.namespace().map(JString(_)).toList) val entry = if (isExtended) { JObject( "name" -> JString(ident.name()), "catalog" -> JString(catalog.name()), "namespace" -> nsArray, - "type" -> JString("TABLE"), + "type" -> JString(tableType.get), "isTemporary" -> JBool(false) ) } else { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/ShowTablesSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/ShowTablesSuite.scala index 775ca672f90b2..e0888fee6ce23 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/ShowTablesSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/ShowTablesSuite.scala @@ -17,7 +17,11 @@ package org.apache.spark.sql.execution.command.v2 +import org.json4s._ +import org.json4s.jackson.JsonMethods._ + import org.apache.spark.sql.Row +import org.apache.spark.sql.connector.catalog.{InMemoryRelationCatalog, TableSummary} import org.apache.spark.sql.execution.command import org.apache.spark.util.Utils @@ -26,6 +30,9 @@ import org.apache.spark.util.Utils */ class ShowTablesSuite extends command.ShowTablesSuiteBase with CommandSuiteBase { override def defaultNamespace: Seq[String] = Nil + // Extended JSON now uses TableSummary.tableType(), and TableCatalog.listTableSummaries + // defaults a missing V2 table type property to TableSummary.FOREIGN_TABLE_TYPE. + override def expectedTableTypeInJson: String = TableSummary.FOREIGN_TABLE_TYPE override def expectsSessionTempViews: Boolean = false // The test fails for V1 catalog with the error: @@ -73,6 +80,34 @@ class ShowTablesSuite extends command.ShowTablesSuiteBase with CommandSuiteBase } } + test("show table extended as json returns relation catalog table and view types") { + val relationCatalog = "show_table_extended_json_relation_catalog" + withSQLConf(s"spark.sql.catalog.$relationCatalog" -> + classOf[InMemoryRelationCatalog].getName) { + withNamespaceAndTable("ns", "tbl", relationCatalog) { t => + sql(s"CREATE TABLE $t (id INT) $defaultUsing") + withView(s"$relationCatalog.ns.vw") { + sql(s"CREATE VIEW $relationCatalog.ns.vw AS SELECT 1 AS id") + + val jsonStr = sql( + s"SHOW TABLE EXTENDED IN $relationCatalog.ns LIKE '*' AS JSON") + .collect()(0).getString(0) + val tables = (parse(jsonStr) \ "tables").asInstanceOf[JArray].arr + def entry(name: String): JValue = { + tables.find(e => (e \ "name").extract[String] == name) + .getOrElse(fail(s"Missing $name in SHOW TABLE EXTENDED AS JSON: $tables")) + } + + assert((entry("tbl") \ "type").extract[String] === + TableSummary.FOREIGN_TABLE_TYPE) + assert((entry("vw") \ "type").extract[String] === + TableSummary.VIEW_TABLE_TYPE) + assert(tables.map(e => (e \ "name").extract[String]).toSet === Set("tbl", "vw")) + } + } + } + } + override protected def extendedPartInNonPartedTableError( catalog: String, namespace: String,