Skip to content

Commit 835de4b

Browse files
authored
Fixes the schema generation for JDBC integration (#470)
* Adjusted SQL table/schema reading to accommodate table name The update introduces 'tableName' in the 'JdbcOptions' annotation class and modifies conditions in 'GenerateDataSchemaTask.kt' and 'DataSchemaGenerator.kt' to handle empty 'tableName'. It also includes driver initialisation for Mariadb. This alteration allows greater flexibility when specifying a SQL source, accommodating both SQL queries and direct table names. * Correct the DbUrl extraction and add JDBC class to DbType
1 parent 5c20a0d commit 835de4b

File tree

14 files changed

+114
-22
lines changed

14 files changed

+114
-22
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/ImportDataSchema.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public annotation class CsvOptions(
5252
public annotation class JdbcOptions(
5353
public val user: String = "", // TODO: I'm not sure about the default parameters
5454
public val password: String = "", // TODO: I'm not sure about the default parameters)
55+
public val tableName: String = "",
5556
public val sqlQuery: String = ""
5657
)
5758

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/ImportDataSchema.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public annotation class CsvOptions(
5252
public annotation class JdbcOptions(
5353
public val user: String = "", // TODO: I'm not sure about the default parameters
5454
public val password: String = "", // TODO: I'm not sure about the default parameters)
55+
public val tableName: String = "",
5556
public val sqlQuery: String = ""
5657
)
5758

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/DbType.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ import org.jetbrains.kotlinx.dataframe.io.TableMetadata
1111
* @property [dbTypeInJdbcUrl] The name of the database as specified in the JDBC URL.
1212
*/
1313
public abstract class DbType(public val dbTypeInJdbcUrl: String) {
14+
15+
16+
/**
17+
* Represents the JDBC driver class name for a given database type.
18+
*
19+
* NOTE: It's important for usage in dataframe-gradle-plugin for force class loading.
20+
*
21+
* @return The JDBC driver class name as a [String].
22+
*/
23+
public abstract val driverClassName: String
24+
1425
/**
1526
* Converts the data from the given [ResultSet] into the specified [TableColumnMetadata] type.
1627
*

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/H2.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import kotlin.reflect.typeOf
1818
* NOTE: All date and timestamp related types are converted to String to avoid java.sql.* types.
1919
*/
2020
public object H2 : DbType("h2") {
21+
override val driverClassName: String
22+
get() = "org.h2.Driver"
23+
2124
override fun convertDataFromResultSet(rs: ResultSet, tableColumnMetadata: TableColumnMetadata): Any? {
2225
val name = tableColumnMetadata.name
2326
return when (tableColumnMetadata.sqlTypeName) {

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/MariaDb.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import kotlin.reflect.typeOf
1313
* and to generate the corresponding column schema.
1414
*/
1515
public object MariaDb : DbType("mariadb") {
16+
override val driverClassName: String
17+
get() = "org.mariadb.jdbc.Driver"
18+
1619
override fun convertDataFromResultSet(rs: ResultSet, tableColumnMetadata: TableColumnMetadata): Any? {
1720
val name = tableColumnMetadata.name
1821
return when (tableColumnMetadata.sqlTypeName) {

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/MySql.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import kotlin.reflect.typeOf
1616
* and to generate the corresponding column schema.
1717
*/
1818
public object MySql : DbType("mysql") {
19+
override val driverClassName: String
20+
get() = "com.mysql.jdbc.Driver"
21+
1922
override fun convertDataFromResultSet(rs: ResultSet, tableColumnMetadata: TableColumnMetadata): Any? {
2023
val name = tableColumnMetadata.name
2124
return when (tableColumnMetadata.sqlTypeName) {

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/PostgreSql.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import kotlin.reflect.typeOf
1616
* and to generate the corresponding column schema.
1717
*/
1818
public object PostgreSql : DbType("postgresql") {
19+
override val driverClassName: String
20+
get() = "org.postgresql.Driver"
21+
1922
override fun convertDataFromResultSet(rs: ResultSet, tableColumnMetadata: TableColumnMetadata): Any? {
2023
val name = tableColumnMetadata.name
2124
return when (tableColumnMetadata.sqlTypeName) {

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/Sqlite.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import kotlin.reflect.typeOf
1313
* and to generate the corresponding column schema.
1414
*/
1515
public object Sqlite : DbType("sqlite") {
16+
override val driverClassName: String
17+
get() = "org.sqlite.JDBC"
18+
1619
override fun convertDataFromResultSet(rs: ResultSet, tableColumnMetadata: TableColumnMetadata): Any? {
1720
val name = tableColumnMetadata.name
1821
return when (tableColumnMetadata.sqlTypeName) {

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/db/util.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import java.sql.SQLException
99
* @return the corresponding [DbType].
1010
* @throws RuntimeException if the url is null.
1111
*/
12-
public fun extractDBTypeFromURL(url: String?): DbType {
12+
public fun extractDBTypeFromUrl(url: String?): DbType {
1313
if (url != null) {
1414
return when {
1515
H2.dbTypeInJdbcUrl in url -> H2
@@ -24,3 +24,14 @@ public fun extractDBTypeFromURL(url: String?): DbType {
2424
throw SQLException("Database URL could not be null. The existing value is $url")
2525
}
2626
}
27+
28+
/**
29+
* Retrieves the driver class name from the given JDBC URL.
30+
*
31+
* @param [url] The JDBC URL to extract the driver class name from.
32+
* @return The driver class name as a [String].
33+
*/
34+
public fun driverClassNameFromUrl(url: String): String {
35+
val dbType = extractDBTypeFromUrl(url)
36+
return dbType.driverClassName
37+
}

dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import org.jetbrains.kotlinx.dataframe.DataFrame
1111
import org.jetbrains.kotlinx.dataframe.api.toDataFrame
1212
import org.jetbrains.kotlinx.dataframe.impl.schema.DataFrameSchemaImpl
1313
import org.jetbrains.kotlinx.dataframe.io.db.DbType
14-
import org.jetbrains.kotlinx.dataframe.io.db.H2
15-
import org.jetbrains.kotlinx.dataframe.io.db.Sqlite
16-
import org.jetbrains.kotlinx.dataframe.io.db.extractDBTypeFromURL
14+
import org.jetbrains.kotlinx.dataframe.io.db.extractDBTypeFromUrl
1715
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema
1816

1917
private val logger = KotlinLogging.logger {}
@@ -115,7 +113,7 @@ public fun DataFrame.Companion.readSqlTable(connection: Connection, tableName: S
115113
if (limit > 0) preparedQuery += " LIMIT $limit"
116114

117115
val url = connection.metaData.url
118-
val dbType = extractDBTypeFromURL(url)
116+
val dbType = extractDBTypeFromUrl(url)
119117

120118
connection.createStatement().use { st ->
121119
logger.debug { "Connection with url:${url} is established successfully." }
@@ -182,7 +180,7 @@ public fun DataFrame.Companion.readSqlQuery(connection: Connection, sqlQuery: St
182180
*/
183181
public fun DataFrame.Companion.readSqlQuery(connection: Connection, sqlQuery: String, limit: Int): AnyFrame {
184182
val url = connection.metaData.url
185-
val dbType = extractDBTypeFromURL(url)
183+
val dbType = extractDBTypeFromUrl(url)
186184

187185
var internalSqlQuery = sqlQuery
188186
if (limit > 0) internalSqlQuery += " LIMIT $limit"
@@ -247,7 +245,7 @@ public fun DataFrame.Companion.readResultSet(resultSet: ResultSet, connection: C
247245
*/
248246
public fun DataFrame.Companion.readResultSet(resultSet: ResultSet, connection: Connection, limit: Int): AnyFrame {
249247
val url = connection.metaData.url
250-
val dbType = extractDBTypeFromURL(url)
248+
val dbType = extractDBTypeFromUrl(url)
251249

252250
return readResultSet(resultSet, dbType, limit)
253251
}
@@ -300,7 +298,7 @@ public fun DataFrame.Companion.readAllSqlTables(connection: Connection): List<An
300298
public fun DataFrame.Companion.readAllSqlTables(connection: Connection, limit: Int): List<AnyFrame> {
301299
val metaData = connection.metaData
302300
val url = connection.metaData.url
303-
val dbType = extractDBTypeFromURL(url)
301+
val dbType = extractDBTypeFromUrl(url)
304302

305303
// exclude a system and other tables without data, but it looks like it supported badly for many databases
306304
val tables = metaData.getTables(null, null, null, arrayOf("TABLE"))
@@ -348,7 +346,7 @@ public fun DataFrame.Companion.getSchemaForSqlTable(
348346
tableName: String
349347
): DataFrameSchema {
350348
val url = connection.metaData.url
351-
val dbType = extractDBTypeFromURL(url)
349+
val dbType = extractDBTypeFromUrl(url)
352350

353351
connection.createStatement().use {
354352
logger.debug { "Connection with url:${connection.metaData.url} is established successfully." }
@@ -383,7 +381,7 @@ public fun DataFrame.Companion.getSchemaForSqlQuery(dbConfig: DatabaseConfigurat
383381
*/
384382
public fun DataFrame.Companion.getSchemaForSqlQuery(connection: Connection, sqlQuery: String): DataFrameSchema {
385383
val url = connection.metaData.url
386-
val dbType = extractDBTypeFromURL(url)
384+
val dbType = extractDBTypeFromUrl(url)
387385

388386
connection.createStatement().use { st ->
389387
st.executeQuery(sqlQuery).use { rs ->
@@ -419,7 +417,7 @@ public fun DataFrame.Companion.getSchemaForResultSet(resultSet: ResultSet, dbTyp
419417
*/
420418
public fun DataFrame.Companion.getSchemaForResultSet(resultSet: ResultSet, connection: Connection): DataFrameSchema {
421419
val url = connection.metaData.url
422-
val dbType = extractDBTypeFromURL(url)
420+
val dbType = extractDBTypeFromUrl(url)
423421

424422
val tableColumns = getTableColumnsMetadata(resultSet)
425423
return buildSchemaByTableColumns(tableColumns, dbType)
@@ -446,7 +444,7 @@ public fun DataFrame.Companion.getSchemaForAllSqlTables(dbConfig: DatabaseConfig
446444
public fun DataFrame.Companion.getSchemaForAllSqlTables(connection: Connection): List<DataFrameSchema> {
447445
val metaData = connection.metaData
448446
val url = connection.metaData.url
449-
val dbType = extractDBTypeFromURL(url)
447+
val dbType = extractDBTypeFromUrl(url)
450448

451449
val tableTypes = arrayOf("TABLE")
452450
// exclude system and other tables without data

0 commit comments

Comments
 (0)