better-duck-core. Every method here is part of the core driver API.
1
Add the dependency
chrono, decimal). See Installation
for why the exact version must be pinned.2
Open a connection
The main handle is SQL methods take
better_duck_core::connection::Connection. Open a private in-memory database,
or a file (created if absent):&mut self, so bind conn as mut.Each
Connection::open_in_memory() call creates its own isolated in-memory database — two
such connections do not see each other’s tables. To share one database across connections, open
a Database and connect() from it.3
Run DDL and DML
Use
execute_batch for one or more ;-separated statements (DuckDB does the splitting), and
execute_with to bind positional parameters ($1, $2, …):4
Query and read rows
execute prepares and runs one statement and returns a DuckResult, which is an
Iterator<Item = Result<DuckRow>>. Read columns by name with get (case-sensitive) or by index
with get_idx; each value is a DuckValue:DuckValue is #[non_exhaustive] — always include a _ arm when you match on it, so your
code keeps compiling as new variants are added.5
(Optional) Materialize a result
A
DuckResult holds a live FFI handle. To detach from it — for example to move the result out of
a closure or across threads — call materialize() to get a ResultSet, which holds no FFI
handles and is Send + Sync + Clone:Full example
Where to go next
Connections & Database
Sharing a database, cloning connections,
Config, interrupting queries.Queries, Results & Values
Parameter binding, iterating results,
DuckValue, and TableDescription.Choosing an API
When to reach for the appender, UDFs, Diesel, or Tauri.
DuckDB essentials
Dialect, type mapping, extensions, and engine behavior.