Skip to content

Commit 6dee961

Browse files
authored
Improved SQL<->JDBC mapping (#855)
* Enable debug mode and adjust JDBC type mappings Enabled the dataframe debug mode by default in the gradle.properties file. Updated JDBC type mappings to use more appropriate Kotlin types and improved handling for certain special cases. Adjusted corresponding test cases to align with these changes. * Update type mappings in JDBC tests and implementations Changed several column type mappings in test cases from Float and Char to Double and String respectively for better compliance with JDBC standards. Adjusted main code to handle BLOB types as ByteArray and refined conditional logic in MariaDb and SQLite converters. * Fix array handling in JDBC DataFrame read logic Corrected handling of SQL Array types to properly map them to Kotlin arrays. Updated test cases to include integer array column and verified schema recognition of SQL Array types. * Fix array handling in JDBC DataFrame read logic Corrected handling of SQL Array types to properly map them to Kotlin arrays. Introduced a utility function to cast arrays and refactored the read logic to use it. Updated test cases to include various array columns and verified schema recognition of these types. * Update SQL schema handling to support array and blob types Enhanced the SQL schema handling to accommodate array types in Postgres and improved support for Blob types in MySQL and MariaDB. Also standardized the use of specific timestamps and fixed data type mappings for schemas. * Refactor code for readability and formatting Optimized code layout in several files, including `mysqlTest.kt`, `readJdbc.kt`, and `postgresH2Test.kt`, for enhanced readability. This includes reformatting function definitions, rearranging import statements, and using concise lambda expressions. * Disable debug mode for dataframe in gradle.properties Changed the `kotlin.dataframe.debug` property to `false`, which was previously set to `true`. This adjustment ensures that tests meant for debugging are not mistakenly executed in production environments. * Refactor array handling and casting operations Changed `castArray` to use safe casting and made it private. Improved handling of array element types by checking distinct types and ensuring consistency, with fallback behavior for varying or unknown types. * Fixed linter
1 parent 99f1875 commit 6dee961

File tree

12 files changed

+236
-48
lines changed

12 files changed

+236
-48
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public object MariaDb : DbType("mariadb") {
1818
get() = "org.mariadb.jdbc.Driver"
1919

2020
override fun convertSqlTypeToColumnSchemaValue(tableColumnMetadata: TableColumnMetadata): ColumnSchema? {
21-
if (tableColumnMetadata.sqlTypeName == "SMALLINT") {
21+
if (tableColumnMetadata.sqlTypeName == "SMALLINT" && tableColumnMetadata.javaClassName == "java.lang.Short") {
2222
val kType = Short::class.createType(nullable = tableColumnMetadata.isNullable)
2323
return ColumnSchema.Value(kType)
2424
}
@@ -35,7 +35,7 @@ public object MariaDb : DbType("mariadb") {
3535
)
3636

3737
override fun convertSqlTypeToKType(tableColumnMetadata: TableColumnMetadata): KType? {
38-
if (tableColumnMetadata.sqlTypeName == "SMALLINT") {
38+
if (tableColumnMetadata.sqlTypeName == "SMALLINT" && tableColumnMetadata.javaClassName == "java.lang.Short") {
3939
return Short::class.createType(nullable = tableColumnMetadata.isNullable)
4040
}
4141
return null

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

+94-12
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,16 @@ import java.sql.SQLXML
2626
import java.sql.Time
2727
import java.sql.Timestamp
2828
import java.sql.Types
29+
import java.time.LocalDateTime
30+
import java.time.OffsetDateTime
31+
import java.time.OffsetTime
2932
import java.util.Date
33+
import java.util.UUID
34+
import kotlin.reflect.KClass
3035
import kotlin.reflect.KType
3136
import kotlin.reflect.full.createType
3237
import kotlin.reflect.full.isSupertypeOf
38+
import kotlin.reflect.full.safeCast
3339
import kotlin.reflect.full.starProjectedType
3440

3541
private val logger = KotlinLogging.logger {}
@@ -775,6 +781,10 @@ private fun manageColumnNameDuplication(columnNameCounter: MutableMap<String, In
775781
return name
776782
}
777783

784+
// Utility function to cast arrays based on the type of elements
785+
private fun <T : Any> castArray(array: Array<*>, elementType: KClass<T>): List<T> =
786+
array.mapNotNull { elementType.safeCast(it) }
787+
778788
/**
779789
* Fetches and converts data from a ResultSet into a mutable map.
780790
*
@@ -816,9 +826,15 @@ private fun fetchAndConvertDataFromResultSet(
816826
}
817827

818828
val dataFrame = data.mapIndexed { index, values ->
829+
val correctedValues = if (kotlinTypesForSqlColumns[index]!!.classifier == Array::class) {
830+
handleArrayValues(values)
831+
} else {
832+
values
833+
}
834+
819835
DataColumn.createValueColumn(
820836
name = tableColumns[index].name,
821-
values = values,
837+
values = correctedValues,
822838
infer = convertNullabilityInference(inferNullability),
823839
type = kotlinTypesForSqlColumns[index]!!,
824840
)
@@ -831,6 +847,31 @@ private fun fetchAndConvertDataFromResultSet(
831847
return dataFrame
832848
}
833849

850+
private fun handleArrayValues(values: MutableList<Any?>): List<Any> {
851+
// Intermediate variable for the first mapping
852+
val sqlArrays = values.mapNotNull {
853+
(it as? java.sql.Array)?.array?.let { array -> array as? Array<*> }
854+
}
855+
856+
// Flatten the arrays to iterate through all elements and filter out null values, then map to component types
857+
val allElementTypes = sqlArrays
858+
.flatMap { array ->
859+
(array.javaClass.componentType?.kotlin?.let { listOf(it) } ?: emptyList())
860+
} // Get the component type of each array and convert it to a Kotlin class, if available
861+
862+
// Find distinct types and ensure there's only one distinct type
863+
val commonElementType = allElementTypes
864+
.distinct() // Get unique element types
865+
.singleOrNull() // Ensure there's only one unique element type, otherwise return null
866+
?: Any::class // Fallback to Any::class if multiple distinct types or no elements found
867+
868+
return if (commonElementType != Any::class) {
869+
sqlArrays.map { castArray(it, commonElementType).toTypedArray() }
870+
} else {
871+
sqlArrays
872+
}
873+
}
874+
834875
private fun convertNullabilityInference(inferNullability: Boolean) = if (inferNullability) Infer.Nulls else Infer.None
835876

836877
private fun extractNewRowFromResultSetAndAddToData(
@@ -843,6 +884,7 @@ private fun extractNewRowFromResultSetAndAddToData(
843884
data[i].add(
844885
try {
845886
rs.getObject(i + 1)
887+
// TODO: add a special handler for Blob via Streams
846888
} catch (_: Throwable) {
847889
val kType = kotlinTypesForSqlColumns[i]!!
848890
// TODO: expand for all the types like in generateKType function
@@ -868,7 +910,7 @@ private fun generateKType(dbType: DbType, tableColumnMetadata: TableColumnMetada
868910
* Creates a mapping between common SQL types and their corresponding KTypes.
869911
*
870912
* @param tableColumnMetadata The metadata of the table column.
871-
* @return The KType associated with the SQL type, or a default type if no mapping is found.
913+
* @return The KType associated with the SQL type or a default type if no mapping is found.
872914
*/
873915
private fun makeCommonSqlToKTypeMapping(tableColumnMetadata: TableColumnMetadata): KType {
874916
val jdbcTypeToKTypeMapping = mapOf(
@@ -882,7 +924,7 @@ private fun makeCommonSqlToKTypeMapping(tableColumnMetadata: TableColumnMetadata
882924
Types.DOUBLE to Double::class,
883925
Types.NUMERIC to BigDecimal::class,
884926
Types.DECIMAL to BigDecimal::class,
885-
Types.CHAR to Char::class,
927+
Types.CHAR to String::class,
886928
Types.VARCHAR to String::class,
887929
Types.LONGVARCHAR to String::class,
888930
Types.DATE to Date::class,
@@ -892,27 +934,67 @@ private fun makeCommonSqlToKTypeMapping(tableColumnMetadata: TableColumnMetadata
892934
Types.VARBINARY to ByteArray::class,
893935
Types.LONGVARBINARY to ByteArray::class,
894936
Types.NULL to String::class,
895-
Types.OTHER to Any::class,
896937
Types.JAVA_OBJECT to Any::class,
897938
Types.DISTINCT to Any::class,
898939
Types.STRUCT to Any::class,
899-
Types.ARRAY to Array<Any>::class,
900-
Types.BLOB to Blob::class,
940+
Types.ARRAY to Array::class,
941+
Types.BLOB to ByteArray::class,
901942
Types.CLOB to Clob::class,
902943
Types.REF to Ref::class,
903944
Types.DATALINK to Any::class,
904945
Types.BOOLEAN to Boolean::class,
905946
Types.ROWID to RowId::class,
906-
Types.NCHAR to Char::class,
947+
Types.NCHAR to String::class,
907948
Types.NVARCHAR to String::class,
908949
Types.LONGNVARCHAR to String::class,
909950
Types.NCLOB to NClob::class,
910951
Types.SQLXML to SQLXML::class,
911952
Types.REF_CURSOR to Ref::class,
912-
Types.TIME_WITH_TIMEZONE to Time::class,
913-
Types.TIMESTAMP_WITH_TIMEZONE to Timestamp::class,
953+
Types.TIME_WITH_TIMEZONE to OffsetTime::class,
954+
Types.TIMESTAMP_WITH_TIMEZONE to OffsetDateTime::class,
914955
)
915-
// TODO: check mapping of JDBC types and classes correctly
916-
val kClass = jdbcTypeToKTypeMapping[tableColumnMetadata.jdbcType] ?: String::class
917-
return kClass.createType(nullable = tableColumnMetadata.isNullable)
956+
957+
fun determineKotlinClass(tableColumnMetadata: TableColumnMetadata): KClass<*> =
958+
when {
959+
tableColumnMetadata.jdbcType == Types.OTHER -> when (tableColumnMetadata.javaClassName) {
960+
"[B" -> ByteArray::class
961+
else -> Any::class
962+
}
963+
964+
tableColumnMetadata.javaClassName == "[B" -> ByteArray::class
965+
966+
tableColumnMetadata.javaClassName == "java.sql.Blob" -> Blob::class
967+
968+
tableColumnMetadata.jdbcType == Types.TIMESTAMP &&
969+
tableColumnMetadata.javaClassName == "java.time.LocalDateTime" -> LocalDateTime::class
970+
971+
tableColumnMetadata.jdbcType == Types.BINARY &&
972+
tableColumnMetadata.javaClassName == "java.util.UUID" -> UUID::class
973+
974+
tableColumnMetadata.jdbcType == Types.REAL &&
975+
tableColumnMetadata.javaClassName == "java.lang.Double" -> Double::class
976+
977+
tableColumnMetadata.jdbcType == Types.FLOAT &&
978+
tableColumnMetadata.javaClassName == "java.lang.Double" -> Double::class
979+
980+
tableColumnMetadata.jdbcType == Types.NUMERIC &&
981+
tableColumnMetadata.javaClassName == "java.lang.Double" -> Double::class
982+
983+
else -> jdbcTypeToKTypeMapping[tableColumnMetadata.jdbcType] ?: String::class
984+
}
985+
986+
fun createArrayTypeIfNeeded(kClass: KClass<*>, isNullable: Boolean): KType =
987+
if (kClass == Array::class) {
988+
val typeParam = kClass.typeParameters[0].createType()
989+
kClass.createType(
990+
arguments = listOf(kotlin.reflect.KTypeProjection.invariant(typeParam)),
991+
nullable = isNullable,
992+
)
993+
} else {
994+
kClass.createType(nullable = isNullable)
995+
}
996+
997+
val kClass: KClass<*> = determineKotlinClass(tableColumnMetadata)
998+
val kType = createArrayTypeIfNeeded(kClass, tableColumnMetadata.isNullable)
999+
return kType
9181000
}

dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/h2Test.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class JdbcTest {
165165

166166
val dataSchema = DataFrame.getSchemaForSqlTable(connection, tableName)
167167
dataSchema.columns.size shouldBe 2
168-
dataSchema.columns["characterCol"]!!.type shouldBe typeOf<Char?>()
168+
dataSchema.columns["characterCol"]!!.type shouldBe typeOf<String?>()
169169
}
170170

171171
@Test
@@ -291,6 +291,7 @@ class JdbcTest {
291291

292292
val schema = DataFrame.getSchemaForSqlTable(connection, tableName)
293293

294+
schema.columns["characterCol"]!!.type shouldBe typeOf<String?>()
294295
schema.columns["tinyIntCol"]!!.type shouldBe typeOf<Int?>()
295296
schema.columns["smallIntCol"]!!.type shouldBe typeOf<Int?>()
296297
schema.columns["bigIntCol"]!!.type shouldBe typeOf<Long?>()

dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/mariadbH2Test.kt

+15-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ import org.junit.AfterClass
1717
import org.junit.BeforeClass
1818
import org.junit.Test
1919
import java.math.BigDecimal
20+
import java.sql.Blob
2021
import java.sql.Connection
2122
import java.sql.DriverManager
2223
import java.sql.SQLException
24+
import java.util.Date
2325
import kotlin.reflect.typeOf
2426

2527
private const val URL = "jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1;MODE=MariaDB;DATABASE_TO_LOWER=TRUE"
@@ -303,10 +305,21 @@ class MariadbH2Test {
303305
val df1 = DataFrame.readSqlTable(connection, "table1").cast<Table1MariaDb>()
304306
val result = df1.filter { it[Table1MariaDb::id] == 1 }
305307
result[0][26] shouldBe "textValue1"
308+
val byteArray = "tinyblobValue".toByteArray()
309+
(result[0][22] as Blob).getBytes(1, byteArray.size) contentEquals byteArray
306310

307311
val schema = DataFrame.getSchemaForSqlTable(connection, "table1")
308312
schema.columns["id"]!!.type shouldBe typeOf<Int>()
309313
schema.columns["textcol"]!!.type shouldBe typeOf<String>()
314+
schema.columns["varbinarycol"]!!.type shouldBe typeOf<ByteArray>()
315+
schema.columns["binarycol"]!!.type shouldBe typeOf<ByteArray>()
316+
schema.columns["longblobcol"]!!.type shouldBe typeOf<Blob>()
317+
schema.columns["tinyblobcol"]!!.type shouldBe typeOf<Blob>()
318+
schema.columns["datecol"]!!.type shouldBe typeOf<Date>()
319+
schema.columns["datetimecol"]!!.type shouldBe typeOf<java.sql.Timestamp>()
320+
schema.columns["timestampcol"]!!.type shouldBe typeOf<java.sql.Timestamp>()
321+
schema.columns["timecol"]!!.type shouldBe typeOf<java.sql.Time>()
322+
schema.columns["yearcol"]!!.type shouldBe typeOf<Int>()
310323

311324
val df2 = DataFrame.readSqlTable(connection, "table2").cast<Table2MariaDb>()
312325
val result2 = df2.filter { it[Table2MariaDb::id] == 1 }
@@ -396,11 +409,11 @@ class MariadbH2Test {
396409
val schema = DataFrame.getSchemaForSqlTable(connection, "table1")
397410

398411
schema.columns["tinyintcol"]!!.type shouldBe typeOf<Int>()
399-
schema.columns["smallintcol"]!!.type shouldBe typeOf<Short?>()
412+
schema.columns["smallintcol"]!!.type shouldBe typeOf<Int?>()
400413
schema.columns["mediumintcol"]!!.type shouldBe typeOf<Int>()
401414
schema.columns["mediumintunsignedcol"]!!.type shouldBe typeOf<Int>()
402415
schema.columns["bigintcol"]!!.type shouldBe typeOf<Long>()
403-
schema.columns["floatcol"]!!.type shouldBe typeOf<Float>()
416+
schema.columns["floatcol"]!!.type shouldBe typeOf<Double>()
404417
schema.columns["doublecol"]!!.type shouldBe typeOf<Double>()
405418
schema.columns["decimalcol"]!!.type shouldBe typeOf<BigDecimal>()
406419
}

dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/mssqlH2Test.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,15 @@ class MSSQLH2Test {
191191
schema.columns["bigintColumn"]!!.type shouldBe typeOf<Long?>()
192192
schema.columns["binaryColumn"]!!.type shouldBe typeOf<ByteArray?>()
193193
schema.columns["bitColumn"]!!.type shouldBe typeOf<Boolean?>()
194-
schema.columns["charColumn"]!!.type shouldBe typeOf<Char?>()
194+
schema.columns["charColumn"]!!.type shouldBe typeOf<String?>()
195195
schema.columns["dateColumn"]!!.type shouldBe typeOf<Date?>()
196196
schema.columns["datetime3Column"]!!.type shouldBe typeOf<java.sql.Timestamp?>()
197197
schema.columns["datetime2Column"]!!.type shouldBe typeOf<java.sql.Timestamp?>()
198198
schema.columns["decimalColumn"]!!.type shouldBe typeOf<BigDecimal?>()
199+
schema.columns["floatColumn"]!!.type shouldBe typeOf<Double?>()
199200
schema.columns["intColumn"]!!.type shouldBe typeOf<Int?>()
200201
schema.columns["moneyColumn"]!!.type shouldBe typeOf<BigDecimal?>()
201-
schema.columns["ncharColumn"]!!.type shouldBe typeOf<Char?>()
202+
schema.columns["ncharColumn"]!!.type shouldBe typeOf<String?>()
202203
schema.columns["ntextColumn"]!!.type shouldBe typeOf<String?>()
203204
schema.columns["numericColumn"]!!.type shouldBe typeOf<BigDecimal?>()
204205
schema.columns["nvarcharColumn"]!!.type shouldBe typeOf<String?>()

dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/mysqlH2Test.kt

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import java.math.BigDecimal
2020
import java.sql.Connection
2121
import java.sql.DriverManager
2222
import java.sql.SQLException
23+
import java.util.Date
2324
import kotlin.reflect.typeOf
2425

2526
// NOTE: the names of testing databases should be different to avoid collisions and should not contain the system names itself
@@ -306,6 +307,15 @@ class MySqlH2Test {
306307
val schema = DataFrame.getSchemaForSqlTable(connection, "table1")
307308
schema.columns["id"]!!.type shouldBe typeOf<Int>()
308309
schema.columns["textcol"]!!.type shouldBe typeOf<String>()
310+
schema.columns["datecol"]!!.type shouldBe typeOf<Date>()
311+
schema.columns["datetimecol"]!!.type shouldBe typeOf<java.sql.Timestamp>()
312+
schema.columns["timestampcol"]!!.type shouldBe typeOf<java.sql.Timestamp>()
313+
schema.columns["timecol"]!!.type shouldBe typeOf<java.sql.Time>()
314+
schema.columns["yearcol"]!!.type shouldBe typeOf<Int>()
315+
schema.columns["varbinarycol"]!!.type shouldBe typeOf<ByteArray>()
316+
schema.columns["binarycol"]!!.type shouldBe typeOf<ByteArray>()
317+
schema.columns["longblobcol"]!!.type shouldBe typeOf<java.sql.Blob>()
318+
schema.columns["tinyblobcol"]!!.type shouldBe typeOf<java.sql.Blob>()
309319

310320
val df2 = DataFrame.readSqlTable(connection, "table2").cast<Table2MySql>()
311321
val result2 = df2.filter { it[Table2MySql::id] == 1 }
@@ -403,7 +413,7 @@ class MySqlH2Test {
403413
schema.columns["mediumintcol"]!!.type shouldBe typeOf<Int>()
404414
schema.columns["mediumintunsignedcol"]!!.type shouldBe typeOf<Int>()
405415
schema.columns["bigintcol"]!!.type shouldBe typeOf<Long>()
406-
schema.columns["floatcol"]!!.type shouldBe typeOf<Float>()
416+
schema.columns["floatcol"]!!.type shouldBe typeOf<Double>()
407417
schema.columns["doublecol"]!!.type shouldBe typeOf<Double>()
408418
schema.columns["decimalcol"]!!.type shouldBe typeOf<BigDecimal>()
409419
}

dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/postgresH2Test.kt

+33-3
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ class PostgresH2Test {
9090
charCol char not null,
9191
dateCol date not null,
9292
doubleCol double precision not null,
93-
integerCol integer
93+
integerCol integer,
94+
intArrayCol integer array,
95+
doubleArrayCol double precision array,
96+
dateArrayCol date array,
97+
textArrayCol text array,
98+
booleanArrayCol boolean array
9499
)
95100
"""
96101
connection.createStatement().execute(createTableStatement.trimIndent())
@@ -120,8 +125,9 @@ class PostgresH2Test {
120125
bigintCol, smallintCol, bigserialCol, booleanCol,
121126
byteaCol, characterCol, characterNCol, charCol,
122127
dateCol, doubleCol,
123-
integerCol
124-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
128+
integerCol, intArrayCol,
129+
doubleArrayCol, dateArrayCol, textArrayCol, booleanArrayCol
130+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
125131
"""
126132

127133
@Language("SQL")
@@ -135,6 +141,15 @@ class PostgresH2Test {
135141
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
136142
"""
137143

144+
val intArray = connection.createArrayOf("INTEGER", arrayOf(1, 2, 3))
145+
val doubleArray = connection.createArrayOf("DOUBLE", arrayOf(1.1, 2.2, 3.3))
146+
val dateArray = connection.createArrayOf(
147+
"DATE",
148+
arrayOf(java.sql.Date.valueOf("2023-08-01"), java.sql.Date.valueOf("2023-08-02")),
149+
)
150+
val textArray = connection.createArrayOf("TEXT", arrayOf("Hello", "World"))
151+
val booleanArray = connection.createArrayOf("BOOLEAN", arrayOf(true, false, true))
152+
138153
connection.prepareStatement(insertData1).use { st ->
139154
// Insert data into table1
140155
for (i in 1..3) {
@@ -149,6 +164,11 @@ class PostgresH2Test {
149164
st.setDate(9, java.sql.Date.valueOf("2023-08-01"))
150165
st.setDouble(10, 12.34)
151166
st.setInt(11, 12345 * i)
167+
st.setArray(12, intArray)
168+
st.setArray(13, doubleArray)
169+
st.setArray(14, dateArray)
170+
st.setArray(15, textArray)
171+
st.setArray(16, booleanArray)
152172
st.executeUpdate()
153173
}
154174
}
@@ -191,11 +211,21 @@ class PostgresH2Test {
191211

192212
result[0][0] shouldBe 1
193213
result[0][8] shouldBe "A"
214+
result[0][12] shouldBe arrayOf(1, 2, 3)
215+
result[0][13] shouldBe arrayOf(1.1, 2.2, 3.3)
216+
result[0][14] shouldBe arrayOf(java.sql.Date.valueOf("2023-08-01"), java.sql.Date.valueOf("2023-08-02"))
217+
result[0][15] shouldBe arrayOf("Hello", "World")
218+
result[0][16] shouldBe arrayOf(true, false, true)
194219

195220
val schema = DataFrame.getSchemaForSqlTable(connection, tableName1)
196221
schema.columns["id"]!!.type shouldBe typeOf<Int>()
197222
schema.columns["integercol"]!!.type shouldBe typeOf<Int?>()
198223
schema.columns["smallintcol"]!!.type shouldBe typeOf<Int>()
224+
schema.columns["intarraycol"]!!.type.classifier shouldBe kotlin.Array::class
225+
schema.columns["doublearraycol"]!!.type.classifier shouldBe kotlin.Array::class
226+
schema.columns["datearraycol"]!!.type.classifier shouldBe kotlin.Array::class
227+
schema.columns["textarraycol"]!!.type.classifier shouldBe kotlin.Array::class
228+
schema.columns["booleanarraycol"]!!.type.classifier shouldBe kotlin.Array::class
199229

200230
val tableName2 = "table2"
201231
val df2 = DataFrame.readSqlTable(connection, tableName2).cast<Table2>()

0 commit comments

Comments
 (0)