duckfn 0.0.7

Write DuckDB extensions in plain Rust: attribute macros that turn ordinary functions into scalar/aggregate/table functions, SQL macros and nested LIST/MAP/ARRAY/STRUCT types.
Documentation

duckfn

English | 简体中文

GitHub Docs crates.io docs.rs License: MIT zread

Write DuckDB extensions in plain Rust.

duckfn is a runtime framework for building DuckDB extensions on top of DuckDB's C Extension API. Together with duckfn-macro, a single attribute turns an ordinary Rust function into a DuckDB scalar, aggregate, table or copy function, a SQL macro, a replacement scan, a type cast, or a nested type — no C/C++ glue code, and no local DuckDB build required.

  • Repository: https://github.com/shijianjs/duckfn
  • Built on quack-rs · libduckdb-sys
  • No unsafe to write: no unsafe fn, no raw pointers in your function bodies
  • No DuckDB build required, no C/C++ code
  • Attribute-driven registration through inventory
  • Panic-safe: Rust panics become DuckDB errors instead of unwinding across the FFI boundary
  • Host file system access: read and write through DuckDB's virtual file system (s3://, http(s):// with httpfs, in-memory) from any callback — aggregate functions included — plus one-line helpers such as duckfn::duck_vfs::read_string / write_string / append_string (duckdb-1-5 feature)
  • Works with DuckDB's official multi-platform extension CI

Status: early / experimental. APIs may change before 1.0.

Installation

[dependencies]
duckfn = "0.0.7"

# duckfn itself is built on these two crates; add them explicitly when you use
# their types or builders directly.
quack-rs = "0.16.0"
# `loadable-extension` dispatches through DuckDB's API table instead of linking
# libduckdb, which is what keeps a local DuckDB build unnecessary.
# (headers only — no linked library)
libduckdb-sys = { version = ">=1.4.4, <2", features = ["loadable-extension"] }

If you prefer the macros without the runtime, depend on duckfn-macro directly; otherwise the macros are re-exported by duckfn and no extra dependency is needed.

duckfn has a single feature, duckdb-1-5, which enables what DuckDB's 1.5 C API added: the logical types from DuckDB 1.5 (currently TIME_NS), copy functions, and host file-system access:

duckfn = { version = "0.0.7", features = ["duckdb-1-5"] }

Quick start

use duckfn::{duck_error, duck_scalar_function, duckfn_entrypoint, DuckOptionResult};

/// ```sql
/// SELECT double_it(21);    -- 42
/// SELECT double_it(NULL);  -- NULL
/// SELECT double_it(13);    -- error: unlucky input
/// ```
#[duck_scalar_function]
pub fn double_it(v: Option<i64>) -> DuckOptionResult<i64> {
    if v == Some(13) {
        return Err(duck_error("unlucky input"));
    }
    Ok(v.map(|x| x * 2))
}

// Generate the extension entry point (name must be lowercase + underscores).
duckfn_entrypoint!("my_ext");

The wrapper, the logical types and the registration are all generated, so the snippet above is entirely safe Rust. The only place unsafe shows up is manual registration: #[duck_custom_register] calls quack-rs' unsafe fn register_scalar / register_aggregate / register_table.

Calling the generated module of a #[duck_scalar_function] exposes builders such as scalar_function_builder() and scalar_overload_builder(), so you can register overloads or function sets yourself.

Documentation

The full guide — every attribute and its arguments, the type mapping, the error model, and a runnable example extension — lives at https://shijianjs.github.io/duckfn/:

Page Contents
Attributes All attributes, shared arguments, and manual registration.
Scalar functions Return shapes, NULL handling, overloads.
Aggregate functions Row handlers, state types, parallel aggregation.
Table functions Row structs, named parameters, streaming.
Copy functions Custom file formats for COPY ... TO / COPY ... FROM, built on runtime dynamic columns.
Type casts Overriding CAST for one source/target pair.
Replacement scans Making SELECT * FROM 'data.points' work.
SQL macros Macros from Rust or from .sql files.
Type mapping DuckDB ↔ Rust types, nullability and known gaps.
Errors and panics · Architecture Error handling, expansion, registration and adapters.

中文文档:https://shijianjs.github.io/duckfn/zh-Hans/

Rust API reference: https://docs.rs/duckfn

License

Licensed under the MIT License.