Skip to main content

Crate quack_rs

Crate quack_rs 

Source
Expand description

§quack-rs

A production-grade Rust SDK for building DuckDB loadable extensions.

§Overview

quack-rs encapsulates the hard-won FFI knowledge required to build DuckDB community extensions in Rust. It provides:

  • A correct, panic-free entry point helper via the entry_point module
  • Type-safe builders for registering aggregate functions (aggregate)
  • Safe vector reading and writing helpers (vector)
  • A generic FfiState<T> that eliminates raw pointer management
  • Documented solutions to every known DuckDB Rust FFI pitfall

§Quick Start

// In your extension's src/lib.rs, write the entry point manually:
use quack_rs::entry_point::init_extension;

#[no_mangle]
pub unsafe extern "C" fn my_extension_init_c_api(
    info: libduckdb_sys::duckdb_extension_info,
    access: *const libduckdb_sys::duckdb_extension_access,
) -> bool {
    unsafe {
        init_extension(info, access, quack_rs::DUCKDB_API_VERSION, |con| {
            // register_my_function(con)?;
            Ok(())
        })
    }
}

§Architecture

The SDK is organized into focused modules:

ModulePurpose
entry_pointHelper for the correct {name}_init_c_api C entry point
connectionConnection facade + Registrar trait for version-agnostic registration
aggregateBuilders for aggregate function registration
scalarBuilder for scalar function registration
castBuilder for custom type cast functions
tableBuilder for table function registration
replacement_scanSELECT * FROM 'file.xyz' replacement scan registration
sql_macroSQL macro registration (CREATE MACRO) — no FFI callbacks
vectorSafe helpers for reading/writing DuckDB data vectors
vector::complexSTRUCT / LIST / MAP / ARRAY vector access (child vectors, offsets)
typesDuckDB type system wrappers (TypeId, LogicalType)
intervalINTERVAL → microseconds conversion with overflow checking
errorExtensionError for FFI error propagation
configRAII wrapper for DuckDB database configuration
validateCommunity extension compliance validators
validate::description_ymlParse and validate description.yml metadata
scaffoldProject generator for new extensions (no C++ glue needed)
testingTest harness for aggregate state logic
preludeConvenience re-exports of the most commonly used items
catalogCatalog entry lookup (duckdb-1-5 feature)
client_contextClient context access (duckdb-1-5 feature)
config_optionExtension-defined configuration options (duckdb-1-5 feature)
copy_functionCustom COPY TO handlers (duckdb-1-5 feature)
table_descriptionTable metadata queries (duckdb-1-5 feature)

§Safety

All unsafe code within this SDK is sound and documented. Extension authors must write unsafe extern "C" callback functions (required by DuckDB’s C API), but the SDK’s helpers minimize the surface area of unsafe code within those callbacks. Every unsafe block inside this crate has a // SAFETY: comment explaining the invariants being upheld.

§Design Principles

  1. Thin wrapper: every abstraction must pay for itself in reduced boilerplate or improved safety. When in doubt, prefer simplicity.
  2. No panics across FFI: unwrap() is forbidden in FFI callbacks and entry points.
  3. Bounded version range: libduckdb-sys uses >=1.4.4, <2 to support DuckDB 1.4.x and 1.5.x (including v1.5.1) while preventing silent adoption of breaking changes in future major releases.
  4. Testable business logic: state structs have zero FFI dependencies.

§Pitfalls

See LESSONS.md for all 16 known DuckDB Rust FFI pitfalls, including symptoms, root causes, and fixes.

§Pitfall L1: COMBINE must propagate config fields

DuckDB’s segment tree creates fresh zero-initialized target states via state_init, then calls combine to merge source into them. This means your combine callback MUST copy ALL configuration fields from source to target — not just accumulated data. Any field that defaults to zero will be wrong at finalize time, producing silently incorrect results.

See aggregate::callbacks::CombineFn for details.

Modules§

aggregate
Builders for registering DuckDB aggregate functions.
cast
Builder for registering DuckDB custom cast functions.
config
RAII wrapper for DuckDB database configuration.
connection
Connection — version-agnostic extension registration facade.
entry_point
Extension entry point helper.
error
Error types for DuckDB extension FFI error propagation.
interval
DuckDB INTERVAL type conversion utilities.
prelude
Convenience re-exports for the most commonly used quack-rs items.
replacement_scan
Builder for registering DuckDB replacement scans.
scaffold
Project scaffolding for DuckDB Rust extensions.
scalar
Builder for registering DuckDB scalar functions.
sql_macro
SQL macro registration for DuckDB extensions.
table
Builder for registering DuckDB table functions.
testing
Test utilities for DuckDB extension development.
types
DuckDB type system wrappers.
validate
Validation utilities for DuckDB community extension compliance.
vector
Safe helpers for reading from and writing to DuckDB data vectors.

Macros§

entry_point
Generates the #[no_mangle] unsafe extern "C" entry point for a DuckDB extension.
entry_point_v2
Generates the #[no_mangle] unsafe extern "C" entry point using the version-agnostic Connection facade.

Constants§

DUCKDB_API_VERSION
The DuckDB C API version string required by duckdb_rs_extension_api_init.