Skip to content

Commit a88b15c

Browse files
pan3793LuciferYang
authored andcommitted
[SPARK-54111][CONNECT] Support getCatalogs for SparkConnectDatabaseMetaData
### What changes were proposed in this pull request? Implement `getCatalogs` defined in `java.sql.DatabaseMetaData` for `SparkConnectDatabaseMetaData`. ```java /** * Retrieves the catalog names available in this database. The results * are ordered by catalog name. * * <P>The catalog column is: * <OL> * <LI><B>TABLE_CAT</B> String {code =>} catalog name * </OL> * * return a {code ResultSet} object in which each row has a * single {code String} column that is a catalog name * throws SQLException if a database access error occurs */ ResultSet getCatalogs() throws SQLException; ``` ### Why are the changes needed? Enhance API coverage of the Connect JDBC driver, for example, `get[Catalogs|Schemas|Tables|...]` APIs are used by SQL GUI tools such as DBeaver for displaying the tree category. ### Does this PR introduce _any_ user-facing change? No, the Connect JDBC driver is a new feature under development. ### How was this patch tested? New UT is added. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #52815 from pan3793/SPARK-54111. Authored-by: Cheng Pan <[email protected]> Signed-off-by: yangjie01 <[email protected]> (cherry picked from commit 2be1eb7) Signed-off-by: yangjie01 <[email protected]>
1 parent d29af13 commit a88b15c

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

sql/connect/client/jdbc/src/main/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectDatabaseMetaData.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import org.apache.spark.util.VersionUtils
2525

2626
class SparkConnectDatabaseMetaData(conn: SparkConnectConnection) extends DatabaseMetaData {
2727

28+
import conn.spark.implicits._
29+
2830
override def allProceduresAreCallable: Boolean = false
2931

3032
override def allTablesAreSelectable: Boolean = false
@@ -288,8 +290,14 @@ class SparkConnectDatabaseMetaData(conn: SparkConnectConnection) extends Databas
288290
columnNamePattern: String): ResultSet =
289291
throw new SQLFeatureNotSupportedException
290292

291-
override def getCatalogs: ResultSet =
292-
throw new SQLFeatureNotSupportedException
293+
override def getCatalogs: ResultSet = {
294+
conn.checkOpen()
295+
296+
val df = conn.spark.sql("SHOW CATALOGS")
297+
.select($"catalog".as("TABLE_CAT"))
298+
.orderBy("TABLE_CAT")
299+
new SparkConnectResultSet(df.collectResult())
300+
}
293301

294302
override def getSchemas: ResultSet =
295303
throw new SQLFeatureNotSupportedException

sql/connect/client/jdbc/src/test/scala/org/apache/spark/sql/connect/client/jdbc/SparkConnectDatabaseMetaDataSuite.scala

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,27 @@ package org.apache.spark.sql.connect.client.jdbc
1919

2020
import java.sql.{Array => _, _}
2121

22+
import scala.util.Using
23+
2224
import org.apache.spark.SparkBuildInfo.{spark_version => SPARK_VERSION}
25+
import org.apache.spark.sql.SparkSession
2326
import org.apache.spark.sql.connect.client.jdbc.test.JdbcHelper
24-
import org.apache.spark.sql.connect.test.{ConnectFunSuite, RemoteSparkSession}
27+
import org.apache.spark.sql.connect.test.{ConnectFunSuite, RemoteSparkSession, SQLHelper}
2528
import org.apache.spark.util.VersionUtils
2629

2730
class SparkConnectDatabaseMetaDataSuite extends ConnectFunSuite with RemoteSparkSession
28-
with JdbcHelper {
31+
with JdbcHelper with SQLHelper {
2932

3033
def jdbcUrl: String = s"jdbc:sc://localhost:$serverPort"
3134

35+
// catalyst test jar is inaccessible here, but presents at the testing connect server classpath
36+
private val TEST_IN_MEMORY_CATALOG = "org.apache.spark.sql.connector.catalog.InMemoryCatalog"
37+
38+
private def registerCatalog(
39+
name: String, className: String)(implicit spark: SparkSession): Unit = {
40+
spark.conf.set(s"spark.sql.catalog.$name", className)
41+
}
42+
3243
test("SparkConnectDatabaseMetaData simple methods") {
3344
withConnection { conn =>
3445
val spark = conn.asInstanceOf[SparkConnectConnection].spark
@@ -199,4 +210,29 @@ class SparkConnectDatabaseMetaDataSuite extends ConnectFunSuite with RemoteSpark
199210
// scalastyle:on line.size.limit
200211
}
201212
}
213+
214+
test("SparkConnectDatabaseMetaData getCatalogs") {
215+
withConnection { conn =>
216+
implicit val spark: SparkSession = conn.asInstanceOf[SparkConnectConnection].spark
217+
218+
registerCatalog("testcat", TEST_IN_MEMORY_CATALOG)
219+
registerCatalog("testcat2", TEST_IN_MEMORY_CATALOG)
220+
221+
// forcibly initialize the registered catalogs because SHOW CATALOGS only
222+
// returns the initialized catalogs.
223+
spark.sql("USE testcat")
224+
spark.sql("USE testcat2")
225+
spark.sql("USE spark_catalog")
226+
227+
val metadata = conn.getMetaData
228+
Using.resource(metadata.getCatalogs) { rs =>
229+
val catalogs = new Iterator[String] {
230+
def hasNext: Boolean = rs.next()
231+
def next(): String = rs.getString("TABLE_CAT")
232+
}.toSeq
233+
// results are ordered by TABLE_CAT
234+
assert(catalogs === Seq("spark_catalog", "testcat", "testcat2"))
235+
}
236+
}
237+
}
202238
}

0 commit comments

Comments
 (0)