Skip to main content
Requires feature = "arrow". No Arrow library is pulled in — the crate defines the C Data Interface ABI structs directly, so a consumer with arrow-rs reinterprets the handles.
The arrow feature bridges DuckDB results to the Arrow ecosystem through the Arrow C Data Interface, keeping the dependency surface minimal.

Exporting a result

query_arrow(sql, binds) -> Result<ArrowResult> runs SQL and exports the result. binds is the same &mut [&mut dyn AppendAble] as execute_with.

ArrowResult

into_parts returns the source DataChunks too: keep them alive until the arrays have been consumed/released, since an array may reference chunk-owned data.

Handing the data to arrow-rs

Both handle types expose pointers whose layout is identical to arrow-rs’s FFI structs:
  • ArrowSchemaHandle: n_children(), as_ptr() / as_mut_ptr() (reinterpret as FFI_ArrowSchema), and unsafe export_to(dest) to move the schema into a caller allocation (transferring the release responsibility).
  • ArrowArrayHandle: len() / is_empty(), as_ptr() / as_mut_ptr() (as FFI_ArrowArray), and unsafe export_to(dest).
Handles call their release callback on drop, so a plain read via as_ptr leaves ownership with the handle; use export_to only when the consumer takes ownership.

Registering an Arrow stream as a view

unsafe register_arrow(view_name, stream: *mut c_void) -> Result<ArrowView> registers a caller-owned ArrowArrayStream pointer as a queryable DuckDB view and returns an ArrowView guard that drops the view when it falls out of scope. A consumer with arrow-rs exports a RecordBatchReader to an FFI_ArrowArrayStream and passes its address.
Safety contract: the stream must stay valid and untouched until the returned ArrowView guard drops. DuckDB takes over reading (and eventually releasing) it.

See also