@@ -11,6 +11,7 @@ import org.apache.arrow.vector.TimeStampSecVector
1111import org.apache.arrow.vector.VectorSchemaRoot
1212import org.apache.arrow.vector.ipc.ArrowFileReader
1313import org.apache.arrow.vector.ipc.ArrowFileWriter
14+ import org.apache.arrow.vector.ipc.ArrowReader
1415import org.apache.arrow.vector.ipc.ArrowStreamReader
1516import org.apache.arrow.vector.ipc.ArrowStreamWriter
1617import org.apache.arrow.vector.types.FloatingPointPrecision
@@ -21,6 +22,9 @@ import org.apache.arrow.vector.types.pojo.FieldType
2122import org.apache.arrow.vector.types.pojo.Schema
2223import org.apache.arrow.vector.util.ByteArrayReadableSeekableByteChannel
2324import org.apache.arrow.vector.util.Text
25+ import org.duckdb.DuckDBConnection
26+ import org.duckdb.DuckDBResultSet
27+ import org.jetbrains.kotlinx.dataframe.AnyFrame
2428import org.jetbrains.kotlinx.dataframe.DataColumn
2529import org.jetbrains.kotlinx.dataframe.DataFrame
2630import org.jetbrains.kotlinx.dataframe.api.NullabilityOptions
@@ -29,21 +33,24 @@ import org.jetbrains.kotlinx.dataframe.api.columnOf
2933import org.jetbrains.kotlinx.dataframe.api.convertToBoolean
3034import org.jetbrains.kotlinx.dataframe.api.copy
3135import org.jetbrains.kotlinx.dataframe.api.dataFrameOf
36+ import org.jetbrains.kotlinx.dataframe.api.describe
3237import org.jetbrains.kotlinx.dataframe.api.map
3338import org.jetbrains.kotlinx.dataframe.api.pathOf
3439import org.jetbrains.kotlinx.dataframe.api.remove
3540import org.jetbrains.kotlinx.dataframe.api.toColumn
3641import org.jetbrains.kotlinx.dataframe.exceptions.TypeConverterNotFoundException
42+ import org.junit.Assert
3743import org.junit.Test
3844import java.io.ByteArrayInputStream
3945import java.io.ByteArrayOutputStream
4046import java.io.File
4147import java.net.URL
4248import java.nio.channels.Channels
49+ import java.sql.DriverManager
4350import java.time.LocalDate
4451import java.time.LocalDateTime
4552import java.time.ZoneOffset
46- import java.util.Locale
53+ import java.util.*
4754import kotlin.reflect.typeOf
4855
4956internal class ArrowKtTest {
@@ -558,23 +565,26 @@ internal class ArrowKtTest {
558565 }
559566 }
560567
561- @Test
562- fun testArrowReaderExtension () {
568+ private fun expectedSimpleDataFrame (): AnyFrame {
563569 val dates = listOf (
564- LocalDateTime .of(2023 , 11 , 23 , 9 , 30 , 25 ),
570+ LocalDateTime .of(2020 , 11 , 23 , 9 , 30 , 25 ),
565571 LocalDateTime .of(2015 , 5 , 25 , 14 , 20 , 13 ),
566572 LocalDateTime .of(2013 , 6 , 19 , 11 , 20 , 13 ),
567573 LocalDateTime .of(2000 , 1 , 1 , 0 , 0 , 0 )
568574 )
569575
570- val expected = dataFrameOf(
576+ return dataFrameOf(
571577 " string" to listOf (" a" , " b" , " c" , " d" ),
572578 " int" to listOf (1 , 2 , 3 , 4 ),
573579 " float" to listOf (1.0f , 2.0f , 3.0f , 4.0f ),
574580 " double" to listOf (1.0 , 2.0 , 3.0 , 4.0 ),
575581 " datetime" to dates
576582 )
583+ }
577584
585+ @Test
586+ fun testArrowReaderExtension () {
587+ val expected = expectedSimpleDataFrame()
578588 val featherChannel = ByteArrayReadableSeekableByteChannel (expected.saveArrowFeatherToByteArray())
579589 val arrowFileReader = ArrowFileReader (featherChannel, RootAllocator ())
580590 arrowFileReader.toDataFrame() shouldBe expected
@@ -583,4 +593,24 @@ internal class ArrowKtTest {
583593 val arrowStreamReader = ArrowStreamReader (ipcInputStream, RootAllocator ())
584594 arrowStreamReader.toDataFrame() shouldBe expected
585595 }
596+
597+ @Test
598+ fun testDuckDBArrowIntegration () {
599+ val expected = expectedSimpleDataFrame()
600+ val query = """
601+ select 'a' as string, 1 as int, CAST(1.0 as FLOAT) as float, CAST(1.0 as DOUBLE) as double, TIMESTAMP '2020-11-23 09:30:25' as datetime
602+ UNION ALL SELECT 'b', 2, 2.0, 2.0, TIMESTAMP '2015-05-25 14:20:13'
603+ UNION ALL SELECT 'c', 3, 3.0, 3.0, TIMESTAMP '2013-06-19 11:20:13'
604+ UNION ALL SELECT 'd', 4, 4.0, 4.0, TIMESTAMP '2000-01-01 00:00:00'
605+ """ .trimIndent()
606+
607+ Class .forName(" org.duckdb.DuckDBDriver" )
608+ val conn = DriverManager .getConnection(" jdbc:duckdb:" ) as DuckDBConnection
609+ conn.use {
610+ val resultSet = it.createStatement().executeQuery(query) as DuckDBResultSet
611+ val dbArrowReader = resultSet.arrowExportStream(RootAllocator (), 256 ) as ArrowReader
612+ Assert .assertTrue(dbArrowReader.javaClass.name.equals(" org.apache.arrow.c.ArrowArrayStreamReader" ))
613+ DataFrame .readArrow(dbArrowReader) shouldBe expected
614+ }
615+ }
586616}
0 commit comments