From f17bdc2de3cd51ad078daa036a5c9e33ad1e373d Mon Sep 17 00:00:00 2001 From: Nazar Mishturak Date: Mon, 25 Mar 2024 22:15:23 +0200 Subject: [PATCH] Add bindings for Apache Arrow interface (#26) --- DuckDB.NET.Bindings/DuckDBNativeObjects.cs | 51 ++++++++++++++++ DuckDB.NET.Bindings/DuckDBWrapperObjects.cs | 26 +++++++++ .../NativeMethods/NativeMethods.Arrow.cs | 58 +++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 DuckDB.NET.Bindings/NativeMethods/NativeMethods.Arrow.cs diff --git a/DuckDB.NET.Bindings/DuckDBNativeObjects.cs b/DuckDB.NET.Bindings/DuckDBNativeObjects.cs index 23dc1371..56348d2f 100644 --- a/DuckDB.NET.Bindings/DuckDBNativeObjects.cs +++ b/DuckDB.NET.Bindings/DuckDBNativeObjects.cs @@ -108,6 +108,57 @@ public void Dispose() } } +[StructLayout(LayoutKind.Sequential)] +public unsafe struct DuckDBArrowSchema : IDisposable +{ + private byte* format; + private byte* name; + private byte* metadata; + private long flags; + private long n_children; + private DuckDBArrowSchema** children; + private DuckDBArrowSchema* dictionary; + private delegate* unmanaged[Cdecl] release; + private void* private_data; + + public void Dispose() + { + if (release != null) + { + fixed (DuckDBArrowSchema* ptr = &this) + { + release(ptr); + } + } + } +} + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct DuckDBArrowArray : IDisposable +{ + private long length; + private long null_count; + private long offset; + private long n_buffers; + private long n_children; + private byte** buffers; + private DuckDBArrowArray** children; + private DuckDBArrowArray* dictionary; + private delegate* unmanaged[Cdecl] release; + private void* private_data; + + public void Dispose() + { + if (release != null) + { + fixed (DuckDBArrowArray* ptr = &this) + { + release(ptr); + } + } + } +} + [StructLayout(LayoutKind.Sequential)] public struct DuckDBDate { diff --git a/DuckDB.NET.Bindings/DuckDBWrapperObjects.cs b/DuckDB.NET.Bindings/DuckDBWrapperObjects.cs index 916989cb..70b85d07 100644 --- a/DuckDB.NET.Bindings/DuckDBWrapperObjects.cs +++ b/DuckDB.NET.Bindings/DuckDBWrapperObjects.cs @@ -105,4 +105,30 @@ protected override bool ReleaseHandle() NativeMethods.DataChunks.DuckDBDestroyDataChunk(out handle); return true; } +} + +public class DuckDBArrow : SafeHandleZeroOrMinusOneIsInvalid +{ + public DuckDBArrow() : base(true) + { + } + + protected override bool ReleaseHandle() + { + NativeMethods.Arrow.DuckDBDestroyArrow(out handle); + return true; + } +} + +public class DuckDBArrowStream : SafeHandleZeroOrMinusOneIsInvalid +{ + public DuckDBArrowStream() : base(true) + { + } + + protected override bool ReleaseHandle() + { + NativeMethods.Arrow.DuckDBDestroyArrowStream(out handle); + return true; + } } \ No newline at end of file diff --git a/DuckDB.NET.Bindings/NativeMethods/NativeMethods.Arrow.cs b/DuckDB.NET.Bindings/NativeMethods/NativeMethods.Arrow.cs new file mode 100644 index 00000000..3cd46973 --- /dev/null +++ b/DuckDB.NET.Bindings/NativeMethods/NativeMethods.Arrow.cs @@ -0,0 +1,58 @@ +using System; +using System.Runtime.InteropServices; + +namespace DuckDB.NET.Native; + +public partial class NativeMethods +{ + public static class Arrow + { + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_query_arrow")] + public static extern DuckDBState DuckDBQueryArrow(DuckDBNativeConnection connection, SafeUnmanagedMemoryHandle query, out DuckDBArrow result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_query_arrow_schema")] + public static extern DuckDBState DuckDBQueryArrowSchema(DuckDBNativeConnection connection, out DuckDBArrowSchema schema); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_prepared_arrow_schema")] + public static extern DuckDBState DuckDBPreparedArrowSchema(DuckDBPreparedStatement preparedStatement, out DuckDBArrowSchema schema); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_result_arrow_array")] + public static extern DuckDBState DuckDBResultArrowArray(DuckDBResult result, DuckDBDataChunk chunk, out DuckDBArrowArray array); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_query_arrow_array")] + public static extern DuckDBState DuckDBQueryArrowArray(DuckDBArrow result, out DuckDBArrowArray array); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_arrow_column_count")] + public static extern long DuckDBArrowColumnCount(DuckDBArrow result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_arrow_row_count")] + public static extern long DuckDBArrowRowCount(DuckDBArrow result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_arrow_rows_changed")] + public static extern long DuckDBArrowRowsChanged(DuckDBArrow result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_query_arrow_error")] + public static extern IntPtr DuckDBQueryArrowError(DuckDBArrow result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_destroy_arrow")] + public static extern DuckDBState DuckDBDestroyArrow(out IntPtr result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_destroy_arrow_stream")] + public static extern DuckDBState DuckDBDestroyArrowStream(out IntPtr stream_p); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_execute_prepared_arrow")] + public static extern DuckDBState DuckDBExecutePreparedArrow(DuckDBPreparedStatement preparedStatement, out DuckDBArrow result); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_arrow_scan")] + public static extern DuckDBState DuckDBArrowScan(DuckDBNativeConnection connection, SafeUnmanagedMemoryHandle tableName, DuckDBArrowStream arrow); + + [DllImport(DuckDbLibrary, CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_arrow_array_scan")] + public static extern DuckDBState DuckDBArrowArrayScan( + DuckDBNativeConnection connection, + SafeUnmanagedMemoryHandle tableName, + DuckDBArrowSchema arrowSchema, + DuckDBArrowArray arrowArray, + out DuckDBArrowStream stream + ); + } +}