Skip to content

Commit ce45ed4

Browse files
authored
Added JDBC-integration (#451)
* Created a module * Updated a module with the inital integration and test * Added a new complex example for reading with Native SQL Query * Added an implementation for a new complex example for reading with Native SQL Query * Added an implementation for a new complex example for reading with Native SQL Query * Added idea for test * Added mariadb4j integration * Attempt with test containers * Added the H2 support for testing database capabilities * Set up a draft Kotlin logging * Started with ImportDataSchema changes * Started with ImportDataSchema changes * Added missed dependencies * Added simple generation for one table * Finished simple prototype * Added some minor ideas * Fixed bug in the KNB test * Fixed bug in the KNB test * Add JDBC support to dataframe gradle plugin * Added API methods * Finished API methods * Added import data schema annotation support * Added import data schema annotation support * Added force-classloading for drivers * Refactored jdbc * Updated tests * Support schema generation for SqlQuery * Support schema generation for SqlQuery * Added experimental methods * Added experimental methods * Added experimental methods * Added H2 types support * Added SQlite types support * Added initial Postgre test data * Fixed PostgreSQL mapping * Made test green * Added type mapping for mariadb and mysql * Add test for mariadb * Added initial support for Mariadb * Refactored sealed hierarchy and fixed SQlite tests * Updated test and moved coverage above 60 percentage * Implemented readAllTables function for H2 * Implemented readAllTables for other databases * Added documentation * Fixed in plugins * Fixed in plugins * Refactored toml * Fixed symbol processing plugin * Added integration test * Fixed inspections * Added documentation * Update SQL reading documentation * Fixed Review Part 1 * Fixed Review Part 1 * Rename test files to match Kotlin conventions and refactor tests * Refactor readAllTables method name to readAllSqlTables * Enhance exception messages and add uniqueness check * Added buildTableMetadata method to DbType and handle JSON type issues * Ignore test cases due to configuration issues. * Remove SQL reading features
1 parent 80e346f commit ce45ed4

File tree

43 files changed

+3613
-87
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3613
-87
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ dependencies {
3737
api(project(":dataframe-arrow"))
3838
api(project(":dataframe-excel"))
3939
api(project(":dataframe-openapi"))
40+
api(project(":dataframe-jdbc"))
4041
}
4142

4243
allprojects {

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,24 @@ import org.jetbrains.kotlinx.dataframe.io.JSON
88

99
/**
1010
* Annotation preprocessing will generate a DataSchema interface from the data at `path`.
11-
* Data must be of supported format: CSV, JSON, Apache Arrow, Excel, OpenAPI (Swagger) in YAML/JSON.
11+
* Data must be of supported format: CSV, JSON, Apache Arrow, Excel, OpenAPI (Swagger) in YAML/JSON, JDBC.
1212
* Generated data schema has properties inferred from data and a companion object with `read method`.
1313
* `read method` is either `readCSV` or `readJson` that returns `DataFrame<name>`
1414
*
1515
* @param name name of the generated interface
1616
* @param path URL or relative path to data.
17-
* if path starts with protocol (http, https, ftp), it's considered a URL. Otherwise, it's treated as relative path.
17+
* If a path starts with protocol (http, https, ftp, jdbc), it's considered a URL.
18+
* Otherwise, it's treated as a relative path.
1819
* By default, it will be resolved relatively to project dir, i.e. File(projectDir, path)
19-
* You can configure it by passing `dataframe.resolutionDir` option to preprocessor, see https://kotlinlang.org/docs/ksp-quickstart.html#pass-options-to-processors
20+
* You can configure it by passing `dataframe.resolutionDir` option to preprocessor,
21+
* see https://kotlinlang.org/docs/ksp-quickstart.html#pass-options-to-processors
2022
* @param visibility visibility of the generated interface.
2123
* @param normalizationDelimiters if not empty, split property names by delimiters,
2224
* lowercase parts and join to camel case. Set empty list to disable normalization
2325
* @param withDefaultPath if `true`, generate `defaultPath` property to the data schema's companion object and make it default argument for a `read method`
2426
* @param csvOptions options to parse CSV data. Not used when data is not Csv
2527
* @param jsonOptions options to parse JSON data. Not used when data is not Json
28+
* @param jdbcOptions options to parse data from a database via JDBC. Not used when data is not stored in the database
2629
*/
2730
@Retention(AnnotationRetention.SOURCE)
2831
@Target(AnnotationTarget.FILE)
@@ -35,6 +38,7 @@ public annotation class ImportDataSchema(
3538
val withDefaultPath: Boolean = true,
3639
val csvOptions: CsvOptions = CsvOptions(','),
3740
val jsonOptions: JsonOptions = JsonOptions(),
41+
val jdbcOptions: JdbcOptions = JdbcOptions(),
3842
)
3943

4044
public enum class DataSchemaVisibility {
@@ -45,6 +49,12 @@ public annotation class CsvOptions(
4549
public val delimiter: Char,
4650
)
4751

52+
public annotation class JdbcOptions(
53+
public val user: String = "", // TODO: I'm not sure about the default parameters
54+
public val password: String = "", // TODO: I'm not sure about the default parameters)
55+
public val sqlQuery: String = ""
56+
)
57+
4858
public annotation class JsonOptions(
4959

5060
/** Allows the choice of how to handle type clashes when reading a JSON file. */

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethods.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ private const val verify = "verify" // cast(true) is obscure, i think it's bette
2424
private const val readCSV = "readCSV"
2525
private const val readTSV = "readTSV"
2626
private const val readJson = "readJson"
27+
private const val readJdbc = "readJdbc"
2728

2829
public abstract class AbstractDefaultReadMethod(
2930
private val path: String?,

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/schema/DataFrameSchemaImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import org.jetbrains.kotlinx.dataframe.schema.ColumnSchema
55
import org.jetbrains.kotlinx.dataframe.schema.CompareResult
66
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema
77

8-
internal class DataFrameSchemaImpl(override val columns: Map<String, ColumnSchema>) : DataFrameSchema {
8+
public class DataFrameSchemaImpl(override val columns: Map<String, ColumnSchema>) : DataFrameSchema {
99

1010
override fun compare(other: DataFrameSchema): CompareResult {
1111
require(other is DataFrameSchemaImpl)

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,15 @@ internal class Integration(
169169
if (version != null) {
170170
dependencies(
171171
"org.jetbrains.kotlinx:dataframe-excel:$version",
172+
"org.jetbrains.kotlinx:dataframe-jdbc:$version",
172173
"org.jetbrains.kotlinx:dataframe-arrow:$version",
173174
"org.jetbrains.kotlinx:dataframe-openapi:$version",
174175
)
175176
}
176177

177178
try {
178179
setMinimalKernelVersion(MIN_KERNEL_VERSION)
179-
} catch (_: NoSuchMethodError) { // will be thrown on version < 0.11.0.198
180+
} catch (_: NoSuchMethodError) { // will be thrown when a version < 0.11.0.198
180181
throw IllegalStateException(
181182
getKernelUpdateMessage(notebook.kernelVersion, MIN_KERNEL_VERSION, notebook.jupyterClientType)
182183
)

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,24 @@ import org.jetbrains.kotlinx.dataframe.io.JSON
88

99
/**
1010
* Annotation preprocessing will generate a DataSchema interface from the data at `path`.
11-
* Data must be of supported format: CSV, JSON, Apache Arrow, Excel, OpenAPI (Swagger) in YAML/JSON.
11+
* Data must be of supported format: CSV, JSON, Apache Arrow, Excel, OpenAPI (Swagger) in YAML/JSON, JDBC.
1212
* Generated data schema has properties inferred from data and a companion object with `read method`.
1313
* `read method` is either `readCSV` or `readJson` that returns `DataFrame<name>`
1414
*
1515
* @param name name of the generated interface
1616
* @param path URL or relative path to data.
17-
* if path starts with protocol (http, https, ftp), it's considered a URL. Otherwise, it's treated as relative path.
17+
* If a path starts with protocol (http, https, ftp, jdbc), it's considered a URL.
18+
* Otherwise, it's treated as a relative path.
1819
* By default, it will be resolved relatively to project dir, i.e. File(projectDir, path)
19-
* You can configure it by passing `dataframe.resolutionDir` option to preprocessor, see https://kotlinlang.org/docs/ksp-quickstart.html#pass-options-to-processors
20+
* You can configure it by passing `dataframe.resolutionDir` option to preprocessor,
21+
* see https://kotlinlang.org/docs/ksp-quickstart.html#pass-options-to-processors
2022
* @param visibility visibility of the generated interface.
2123
* @param normalizationDelimiters if not empty, split property names by delimiters,
2224
* lowercase parts and join to camel case. Set empty list to disable normalization
2325
* @param withDefaultPath if `true`, generate `defaultPath` property to the data schema's companion object and make it default argument for a `read method`
2426
* @param csvOptions options to parse CSV data. Not used when data is not Csv
2527
* @param jsonOptions options to parse JSON data. Not used when data is not Json
28+
* @param jdbcOptions options to parse data from a database via JDBC. Not used when data is not stored in the database
2629
*/
2730
@Retention(AnnotationRetention.SOURCE)
2831
@Target(AnnotationTarget.FILE)
@@ -35,6 +38,7 @@ public annotation class ImportDataSchema(
3538
val withDefaultPath: Boolean = true,
3639
val csvOptions: CsvOptions = CsvOptions(','),
3740
val jsonOptions: JsonOptions = JsonOptions(),
41+
val jdbcOptions: JdbcOptions = JdbcOptions(),
3842
)
3943

4044
public enum class DataSchemaVisibility {
@@ -45,6 +49,12 @@ public annotation class CsvOptions(
4549
public val delimiter: Char,
4650
)
4751

52+
public annotation class JdbcOptions(
53+
public val user: String = "", // TODO: I'm not sure about the default parameters
54+
public val password: String = "", // TODO: I'm not sure about the default parameters)
55+
public val sqlQuery: String = ""
56+
)
57+
4858
public annotation class JsonOptions(
4959

5060
/** Allows the choice of how to handle type clashes when reading a JSON file. */

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/codeGen/DefaultReadDfMethods.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ private const val verify = "verify" // cast(true) is obscure, i think it's bette
2424
private const val readCSV = "readCSV"
2525
private const val readTSV = "readTSV"
2626
private const val readJson = "readJson"
27+
private const val readJdbc = "readJdbc"
2728

2829
public abstract class AbstractDefaultReadMethod(
2930
private val path: String?,

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/schema/DataFrameSchemaImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import org.jetbrains.kotlinx.dataframe.schema.ColumnSchema
55
import org.jetbrains.kotlinx.dataframe.schema.CompareResult
66
import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema
77

8-
internal class DataFrameSchemaImpl(override val columns: Map<String, ColumnSchema>) : DataFrameSchema {
8+
public class DataFrameSchemaImpl(override val columns: Map<String, ColumnSchema>) : DataFrameSchema {
99

1010
override fun compare(other: DataFrameSchema): CompareResult {
1111
require(other is DataFrameSchemaImpl)

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,15 @@ internal class Integration(
169169
if (version != null) {
170170
dependencies(
171171
"org.jetbrains.kotlinx:dataframe-excel:$version",
172+
"org.jetbrains.kotlinx:dataframe-jdbc:$version",
172173
"org.jetbrains.kotlinx:dataframe-arrow:$version",
173174
"org.jetbrains.kotlinx:dataframe-openapi:$version",
174175
)
175176
}
176177

177178
try {
178179
setMinimalKernelVersion(MIN_KERNEL_VERSION)
179-
} catch (_: NoSuchMethodError) { // will be thrown on version < 0.11.0.198
180+
} catch (_: NoSuchMethodError) { // will be thrown when a version < 0.11.0.198
180181
throw IllegalStateException(
181182
getKernelUpdateMessage(notebook.kernelVersion, MIN_KERNEL_VERSION, notebook.jupyterClientType)
182183
)

dataframe-excel/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/xlsx.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ internal class DefaultReadExcelMethod(path: String?) : AbstractDefaultReadMethod
5757
private const val readExcel = "readExcel"
5858

5959
/**
60-
* @param sheetName sheet to read. By default, first sheet in the document
60+
* @param sheetName sheet to read. By default, the first sheet in the document
6161
* @param columns comma separated list of Excel column letters and column ranges (e.g. “A:E” or “A,C,E:F”)
6262
* @param skipRows number of rows before header
6363
* @param rowsCount number of rows to read.
@@ -77,7 +77,7 @@ public fun DataFrame.Companion.readExcel(
7777
}
7878

7979
/**
80-
* @param sheetName sheet to read. By default, first sheet in the document
80+
* @param sheetName sheet to read. By default, the first sheet in the document
8181
* @param columns comma separated list of Excel column letters and column ranges (e.g. “A:E” or “A,C,E:F”)
8282
* @param skipRows number of rows before header
8383
* @param rowsCount number of rows to read.
@@ -97,7 +97,7 @@ public fun DataFrame.Companion.readExcel(
9797
}
9898

9999
/**
100-
* @param sheetName sheet to read. By default, first sheet in the document
100+
* @param sheetName sheet to read. By default, the first sheet in the document
101101
* @param columns comma separated list of Excel column letters and column ranges (e.g. “A:E” or “A,C,E:F”)
102102
* @param skipRows number of rows before header
103103
* @param rowsCount number of rows to read.
@@ -114,7 +114,7 @@ public fun DataFrame.Companion.readExcel(
114114
): AnyFrame = readExcel(asURL(fileOrUrl), sheetName, skipRows, columns, rowsCount, nameRepairStrategy)
115115

116116
/**
117-
* @param sheetName sheet to read. By default, first sheet in the document
117+
* @param sheetName sheet to read. By default, the first sheet in the document
118118
* @param columns comma separated list of Excel column letters and column ranges (e.g. “A:E” or “A,C,E:F”)
119119
* @param skipRows number of rows before header
120120
* @param rowsCount number of rows to read.
@@ -134,7 +134,7 @@ public fun DataFrame.Companion.readExcel(
134134
}
135135

136136
/**
137-
* @param sheetName sheet to read. By default, first sheet in the document
137+
* @param sheetName sheet to read. By default, the first sheet in the document
138138
* @param columns comma separated list of Excel column letters and column ranges (e.g. “A:E” or “A,C,E:F”)
139139
* @param skipRows number of rows before header
140140
* @param rowsCount number of rows to read.
@@ -446,18 +446,18 @@ private fun Cell.setCellValueByGuessedType(any: Any) {
446446

447447
/**
448448
* Set LocalDateTime value correctly also if date have zero value in Excel.
449-
* Zero date is usually used fore storing time component only,
450-
* is displayed as 00.01.1900 in Excel and as 30.12.1899 in LibreOffice Calc and also in POI.
449+
* Zero dates are usually used for storing a time component only,
450+
* are displayed as 00.01.1900 in Excel and as 30.12.1899 in LibreOffice Calc and also in POI.
451451
* POI can not set 1899 year directly.
452452
*/
453453
private fun Cell.setTime(localDateTime: LocalDateTime) {
454454
this.setCellValue(DateUtil.getExcelDate(localDateTime.plusDays(1)) - 1.0)
455455
}
456456

457457
/**
458-
* Set Date value correctly also if date have zero value in Excel.
459-
* Zero date is usually used fore storing time component only,
460-
* is displayed as 00.01.1900 in Excel and as 30.12.1899 in LibreOffice Calc and also in POI.
458+
* Set Date value correctly also if date has zero value in Excel.
459+
* Zero dates are usually used for storing a time component only,
460+
* are displayed as 00.01.1900 in Excel and as 30.12.1899 in LibreOffice Calc and also in POI.
461461
* POI can not set 1899 year directly.
462462
*/
463463
private fun Cell.setDate(date: Date) {

0 commit comments

Comments
 (0)