chdb_rust/arrow_stream.rs
1//! Arrow streaming support for chDB.
2//!
3//! This module provides types and functions for registering Arrow streams and arrays
4//! as table functions in chDB, enabling efficient data transfer between Arrow
5//! and ClickHouse formats.
6//!
7//! # Overview
8//!
9//! Arrow streaming allows you to:
10//! - Register Arrow streams as virtual tables that can be queried with SQL
11//! - Register Arrow arrays as virtual tables
12//! - Unregister tables when done
13//!
14//! # Examples
15//!
16//! ```no_run
17//! use chdb_rust::connection::Connection;
18//! use chdb_rust::arrow_stream::{ArrowStream, ArrowSchema, ArrowArray};
19//!
20//! // Create a connection
21//! let conn = Connection::open_in_memory()?;
22//!
23//! // Register an Arrow stream as a table (assuming you have an Arrow stream handle)
24//! // let arrow_stream = ArrowStream::from_raw(stream_ptr);
25//! // conn.register_arrow_stream("my_table", &arrow_stream)?;
26//!
27//! // Query the registered table
28//! // let result = conn.query("SELECT * FROM my_table", OutputFormat::JSONEachRow)?;
29//!
30//! // Unregister when done
31//! // conn.unregister_arrow_table("my_table")?;
32//! # Ok::<(), chdb_rust::error::Error>(())
33//! ```
34
35use crate::bindings;
36
37/// A handle to an Arrow stream.
38///
39/// This is a wrapper around the opaque `chdb_arrow_stream` pointer type.
40/// Arrow streams are typically created from Arrow C++ or other Arrow implementations.
41///
42/// # Safety
43///
44/// The underlying pointer must be valid and must remain valid for the lifetime
45/// of this handle. The handle does not take ownership of the Arrow stream.
46#[derive(Debug, Clone, Copy)]
47pub struct ArrowStream {
48 inner: bindings::chdb_arrow_stream,
49}
50
51unsafe impl Send for ArrowStream {}
52
53impl ArrowStream {
54 /// Create an `ArrowStream` from a raw `chdb_arrow_stream` pointer.
55 ///
56 /// # Safety
57 ///
58 /// The pointer must be valid and point to a valid Arrow stream handle.
59 /// The caller is responsible for ensuring the stream remains valid for
60 /// the lifetime of this handle.
61 ///
62 /// # Arguments
63 ///
64 /// * `stream` - A raw pointer to a `chdb_arrow_stream`
65 ///
66 /// # Examples
67 ///
68 /// ```no_run
69 /// use chdb_rust::arrow_stream::ArrowStream;
70 ///
71 /// // Assuming you have a valid Arrow stream pointer from Arrow C++
72 /// // let stream_ptr: *mut chdb_arrow_stream_ = ...;
73 /// // let arrow_stream = unsafe { ArrowStream::from_raw(stream_ptr) };
74 /// ```
75 pub unsafe fn from_raw(stream: bindings::chdb_arrow_stream) -> Self {
76 Self { inner: stream }
77 }
78
79 /// Get the raw pointer to the underlying Arrow stream handle.
80 ///
81 /// # Returns
82 ///
83 /// Returns the raw `chdb_arrow_stream` pointer.
84 pub fn as_raw(&self) -> bindings::chdb_arrow_stream {
85 self.inner
86 }
87}
88
89/// A handle to an Arrow schema.
90///
91/// This is a wrapper around the opaque `chdb_arrow_schema` pointer type.
92/// Arrow schemas define the structure of Arrow data.
93///
94/// # Safety
95///
96/// The underlying pointer must be valid and must remain valid for the lifetime
97/// of this handle. The handle does not take ownership of the Arrow schema.
98#[derive(Debug, Clone, Copy)]
99pub struct ArrowSchema {
100 inner: bindings::chdb_arrow_schema,
101}
102
103unsafe impl Send for ArrowSchema {}
104
105impl ArrowSchema {
106 /// Create an `ArrowSchema` from a raw `chdb_arrow_schema` pointer.
107 ///
108 /// # Safety
109 ///
110 /// The pointer must be valid and point to a valid Arrow schema handle.
111 /// The caller is responsible for ensuring the schema remains valid for
112 /// the lifetime of this handle.
113 ///
114 /// # Arguments
115 ///
116 /// * `schema` - A raw pointer to a `chdb_arrow_schema`
117 ///
118 /// # Examples
119 ///
120 /// ```no_run
121 /// use chdb_rust::arrow_stream::ArrowSchema;
122 ///
123 /// // Assuming you have a valid Arrow schema pointer from Arrow C++
124 /// // let schema_ptr: *mut chdb_arrow_schema_ = ...;
125 /// // let arrow_schema = unsafe { ArrowSchema::from_raw(schema_ptr) };
126 /// ```
127 pub unsafe fn from_raw(schema: bindings::chdb_arrow_schema) -> Self {
128 Self { inner: schema }
129 }
130
131 /// Get the raw pointer to the underlying Arrow schema handle.
132 ///
133 /// # Returns
134 ///
135 /// Returns the raw `chdb_arrow_schema` pointer.
136 pub fn as_raw(&self) -> bindings::chdb_arrow_schema {
137 self.inner
138 }
139}
140
141/// A handle to an Arrow array.
142///
143/// This is a wrapper around the opaque `chdb_arrow_array` pointer type.
144/// Arrow arrays contain the actual data in Arrow format.
145///
146/// # Safety
147///
148/// The underlying pointer must be valid and must remain valid for the lifetime
149/// of this handle. The handle does not take ownership of the Arrow array.
150#[derive(Debug, Clone, Copy)]
151pub struct ArrowArray {
152 inner: bindings::chdb_arrow_array,
153}
154
155unsafe impl Send for ArrowArray {}
156
157impl ArrowArray {
158 /// Create an `ArrowArray` from a raw `chdb_arrow_array` pointer.
159 ///
160 /// # Safety
161 ///
162 /// The pointer must be valid and point to a valid Arrow array handle.
163 /// The caller is responsible for ensuring the array remains valid for
164 /// the lifetime of this handle.
165 ///
166 /// # Arguments
167 ///
168 /// * `array` - A raw pointer to a `chdb_arrow_array`
169 ///
170 /// # Examples
171 ///
172 /// ```no_run
173 /// use chdb_rust::arrow_stream::ArrowArray;
174 ///
175 /// // Assuming you have a valid Arrow array pointer from Arrow C++
176 /// // let array_ptr: *mut chdb_arrow_array_ = ...;
177 /// // let arrow_array = unsafe { ArrowArray::from_raw(array_ptr) };
178 /// ```
179 pub unsafe fn from_raw(array: bindings::chdb_arrow_array) -> Self {
180 Self { inner: array }
181 }
182
183 /// Get the raw pointer to the underlying Arrow array handle.
184 ///
185 /// # Returns
186 ///
187 /// Returns the raw `chdb_arrow_array` pointer.
188 pub fn as_raw(&self) -> bindings::chdb_arrow_array {
189 self.inner
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn test_arrow_stream_from_raw() {
199 // Test that we can create an ArrowStream from a null pointer
200 // (this is just testing the API, not actual functionality)
201 let null_ptr = std::ptr::null_mut();
202 let stream = unsafe { ArrowStream::from_raw(null_ptr) };
203 assert!(stream.as_raw().is_null());
204 }
205
206 #[test]
207 fn test_arrow_schema_from_raw() {
208 let null_ptr = std::ptr::null_mut();
209 let schema = unsafe { ArrowSchema::from_raw(null_ptr) };
210 assert!(schema.as_raw().is_null());
211 }
212
213 #[test]
214 fn test_arrow_array_from_raw() {
215 let null_ptr = std::ptr::null_mut();
216 let array = unsafe { ArrowArray::from_raw(null_ptr) };
217 assert!(array.as_raw().is_null());
218 }
219}