pub struct Connection(/* private fields */);Expand description
A high-level DuckDB connection.
Connection wraps a RawConnection and exposes a safe, ergonomic API for
opening databases, executing SQL, and creating appenders.
§Example
use better_duck_core::connection::Connection;
let mut conn = Connection::open_in_memory().expect("open in-memory db");
conn.execute_batch("CREATE TABLE t (id INTEGER)").expect("create table");
conn.execute_batch("INSERT INTO t VALUES (1)").expect("insert");Implementations§
Source§impl Connection
impl Connection
Sourcepub fn open<P: AsRef<Path>>(path: P) -> Result<Connection>
pub fn open<P: AsRef<Path>>(path: P) -> Result<Connection>
Opens a connection to a DuckDB database at the given file path.
§Errors
Returns an error if the database cannot be opened or the path contains a nul byte.
Sourcepub fn open_with_flags<P: AsRef<Path>>(
path: P,
config: Config,
) -> Result<Connection>
pub fn open_with_flags<P: AsRef<Path>>( path: P, config: Config, ) -> Result<Connection>
Opens a connection to a DuckDB database at the given path with additional config.
§Errors
Returns an error if the database cannot be opened or the path contains a nul byte.
Source§impl Connection
impl Connection
Sourcepub fn open_in_memory() -> Result<Connection>
pub fn open_in_memory() -> Result<Connection>
Opens an in-memory DuckDB connection.
§Errors
Returns an error if the connection cannot be established.
Sourcepub fn open_in_memory_with_flags(config: Config) -> Result<Connection>
pub fn open_in_memory_with_flags(config: Config) -> Result<Connection>
Opens an in-memory DuckDB connection with additional config.
§Errors
Returns an error if the connection cannot be established.
Source§impl Connection
impl Connection
Sourcepub fn execute_batch(&mut self, sql: impl AsRef<str>) -> Result<()>
pub fn execute_batch(&mut self, sql: impl AsRef<str>) -> Result<()>
Executes one or more SQL statements separated by semicolons.
The result of each statement is discarded. Use this for DDL
(CREATE TABLE, DROP TABLE) and simple DML (INSERT, UPDATE, DELETE).
§Errors
Returns an error if any statement fails to execute.
§Example
let mut conn = Connection::open_in_memory()?;
conn.execute_batch("CREATE TABLE t (id INTEGER)")?;
conn.execute_batch("INSERT INTO t VALUES (1)")?;Sourcepub fn extract_statements(
&self,
sql: impl AsRef<str>,
) -> Result<ExtractedStatements>
pub fn extract_statements( &self, sql: impl AsRef<str>, ) -> Result<ExtractedStatements>
Parses a (possibly multi-statement) SQL string into a batch of individually preparable statements.
DuckDB performs the parsing — there is no Rust-side statement splitting, so
semicolons inside string literals, comments, or dollar-quoted bodies do not
cause a false split. Each statement in the returned
ExtractedStatements batch is
prepared on demand via
prepare.
§Errors
Returns an error if sql contains an interior nul byte, or if DuckDB cannot
parse the batch.
§Examples
let conn = Connection::open_in_memory()?;
let batch = conn.extract_statements("SELECT 1 AS a; SELECT 2 AS b")?;
assert_eq!(batch.len(), 2);
let mut second = batch.prepare(1)?;
let mut rows = second.execute()?;
assert!(rows.next().is_some());Sourcepub fn execute(&mut self, sql: impl AsRef<str>) -> Result<DuckResult>
pub fn execute(&mut self, sql: impl AsRef<str>) -> Result<DuckResult>
Prepares and executes a SQL statement, returning the result.
Works for all statement types:
- SELECT — iterate rows via the
Iteratorimpl onDuckResult. - INSERT / UPDATE / DELETE — check
DuckResult::changes()for affected rows. - DDL (
CREATE TABLE,DROP TABLE, etc.) —.changes()returns0, no rows. - INSERT … RETURNING — both iterate rows and check
.changes().
For parameterized statements use execute_with.
§Errors
Returns an error if DuckDB cannot prepare or execute the statement.
§Examples
let mut conn = Connection::open_in_memory()?;
conn.execute_batch("CREATE TABLE t (id INTEGER)")?;
let n = conn.execute("INSERT INTO t VALUES (1)")?.changes();
assert_eq!(n, 1);Sourcepub fn insert<T: AppendAble, I>(&mut self, sql: &str, values: I) -> Result<()>where
I: IntoIterator<Item = T>,
pub fn insert<T: AppendAble, I>(&mut self, sql: &str, values: I) -> Result<()>where
I: IntoIterator<Item = T>,
Prepares sql, binds each value in values as consecutive positional
parameters ($1, $2, …), and executes the statement once.
All values share a single type T, so this suits a parameterized DML
statement filled from a homogeneous iterator. For heterogeneous binds use
execute_with.
§Errors
Returns an error if preparation, binding, or execution fails, or if the statement reports that no rows changed.
§Examples
let mut conn = Connection::open_in_memory()?;
conn.execute("CREATE TABLE t (a INTEGER, b INTEGER)")?;
conn.insert::<i32, _>("INSERT INTO t VALUES ($1, $2)", [10, 20])?;Sourcepub fn execute_with(
&mut self,
sql: impl AsRef<str>,
binds: &mut [&mut dyn AppendAble],
) -> Result<DuckResult>
pub fn execute_with( &mut self, sql: impl AsRef<str>, binds: &mut [&mut dyn AppendAble], ) -> Result<DuckResult>
Prepares and executes a parameterized SQL statement, returning the result.
§Errors
Returns an error if preparation, binding, or execution fails.
Sourcepub fn table_names(
&self,
query: impl AsRef<str>,
qualified: bool,
) -> Result<Vec<String>>
pub fn table_names( &self, query: impl AsRef<str>, qualified: bool, ) -> Result<Vec<String>>
Returns the table names query reads from, as determined by DuckDB’s own
parser — no custom SQL parsing. Handles quoted/qualified identifiers, CTEs,
joins, and subqueries.
With qualified = true each name is fully qualified (catalog.schema.table);
with false only the bare (unescaped) table name is returned. The order and
de-duplication follow DuckDB. A query that reads no tables yields an empty
vector.
§Errors
Returns an error if query contains an interior NUL. It also returns an error
if DuckDB reports a parse failure by returning a null value.
§Panics / aborts
query must be syntactically valid SQL. On a syntax error the underlying
duckdb_get_table_names throws a C++ ParserException that unwinds across the
FFI boundary; Rust cannot catch a foreign exception, so the process aborts
rather than returning an error. This is an upstream DuckDB C-API defect (the
same one that affects statement extraction), not something this wrapper can
intercept. Validate untrusted SQL elsewhere before calling this.
Sourcepub fn table_description(
&self,
schema: &str,
table: &str,
) -> Result<TableDescription>
pub fn table_description( &self, schema: &str, table: &str, ) -> Result<TableDescription>
Describes schema.table (default catalog), giving indexed access to column
names and DEFAULT flags via TableDescription.
The API has no column-count accessor; obtain the number of columns from a
trusted bounds source (an appender’s column count, or a SELECT … LIMIT 0
schema) and read 0..count.
§Errors
Returns an error if the names contain an interior NUL, or if DuckDB cannot describe the table (the error carries DuckDB’s catalog-aware message).
Sourcepub fn table_description_ext(
&self,
catalog: Option<&str>,
schema: &str,
table: &str,
) -> Result<TableDescription>
pub fn table_description_ext( &self, catalog: Option<&str>, schema: &str, table: &str, ) -> Result<TableDescription>
Like table_description but with an explicit
catalog (None uses DuckDB’s default).
§Errors
As table_description, plus an interior NUL
in catalog.
Sourcepub fn register_logical_type(&self, ty: &LogicalType) -> Result<()>
pub fn register_logical_type(&self, ty: &LogicalType) -> Result<()>
Registers ty as a custom (aliased) logical type in this connection’s
catalog, so its alias can be used as a type name in SQL. Give ty a name
first with LogicalType::set_alias.
§Errors
Returns an error if ty has no alias, or DuckDB rejects the registration
(e.g. a name conflict).
Sourcepub fn execution_is_finished(&self) -> bool
pub fn execution_is_finished(&self) -> bool
Whether the current query on this connection has finished executing.
Meaningful while driving execution manually with the external task scheduler
(TaskState): a background query is done
once this returns true. (duckdb_execution_is_finished.)
Sourcepub fn profiling_info(&self) -> Option<ProfilingNode>
pub fn profiling_info(&self) -> Option<ProfilingNode>
Materialises the connection’s query-profiling tree into an owned
ProfilingNode, or None if profiling is disabled or no query has run.
The tree is copied out eagerly, so it stays valid after later queries and
after the connection is dropped. Enable profiling with
PRAGMA enable_profiling = 'no_output' (and optionally PRAGMA profiling_mode).
Sourcepub fn profiling_metric(&self, key: &str) -> Option<String>
pub fn profiling_metric(&self, key: &str) -> Option<String>
Fetches a single metric from the root profiling node, or None if profiling
is disabled or no query has run.
§Panics / aborts
key must be a metric that exists (e.g. one returned by
profiling_info’s
metrics). Despite its C-API docs, DuckDB’s
duckdb_profiling_info_get_value throws a C++ exception for an unknown key
that unwinds across the FFI boundary and aborts the process — an upstream
defect this wrapper cannot intercept. For a safe all-metrics snapshot use
profiling_info instead.
Sourcepub fn client_context(&self) -> Option<ClientContext<'_>>
pub fn client_context(&self) -> Option<ClientContext<'_>>
Returns this connection’s ClientContext, exposing its stable connection
id. The returned context borrows self, so it cannot outlive the connection.
Returns None if DuckDB does not provide a context for the connection.
Sourcepub fn appender(&mut self, table: &str, schema: &str) -> Result<Appender>
pub fn appender(&mut self, table: &str, schema: &str) -> Result<Appender>
Creates an appender for bulk-inserting rows into the given table and schema.
§Errors
Returns an error if the table does not exist or the appender cannot be created.
Sourcepub fn appender_ext(
&mut self,
catalog: Option<&str>,
schema: &str,
table: &str,
) -> Result<Appender>
pub fn appender_ext( &mut self, catalog: Option<&str>, schema: &str, table: &str, ) -> Result<Appender>
Creates an appender for [catalog.]schema.table in a specific attached
catalog (None uses the default catalog).
§Errors
Returns an error if a name contains an interior NUL, or the appender cannot be created (e.g. the table/catalog does not exist).
Sourcepub fn appender_query(
&mut self,
query: &str,
types: &[LogicalType],
table_name: Option<&str>,
column_names: Option<&[&str]>,
) -> Result<Appender>
pub fn appender_query( &mut self, query: &str, types: &[LogicalType], table_name: Option<&str>, column_names: Option<&[&str]>, ) -> Result<Appender>
Creates a query appender whose appended rows feed query (INSERT/UPDATE/
DELETE/MERGE), referring to the appended data by table_name (default
"appended_data"). types are the appended columns’ types; column_names
optionally names them.
§Errors
Returns an error on an interior NUL in any string, or if DuckDB rejects the query or column set.
Source§impl Connection
impl Connection
Sourcepub fn close(self) -> Result<()>
pub fn close(self) -> Result<()>
Closes the connection explicitly.
This consumes the connection so it cannot be used after closing. The connection is also closed automatically on drop.
§Errors
Returns an error if appenders created from this connection are still alive. The connection stays open in that case and closes once the last of them is dropped.
Sourcepub fn is_open(&self) -> bool
pub fn is_open(&self) -> bool
Returns true if the connection is open.
Always true: close consumes the connection, so a
Connection value can only ever refer to an open connection. Retained so
existing callers keep compiling.
Sourcepub fn db(&self) -> &RawConnection
pub fn db(&self) -> &RawConnection
Returns a reference to the underlying RawConnection.
This provides access to low-level operations such as prepare.
Sourcepub fn try_clone(&self) -> Result<Connection>
pub fn try_clone(&self) -> Result<Connection>
Opens a second, independent connection to the same database as this one.
Cheap: one duckdb_connect call, no file I/O. See Database::connect for
details on what “the same database” means for :memory: connections.
§Errors
Returns an error if the connection cannot be established.
Sourcepub fn query_control(&self) -> QueryControl
pub fn query_control(&self) -> QueryControl
Returns a QueryControl for interrupting or observing the
query running on this connection from another thread.
Mint the control before starting the query (typically on another thread),
then call QueryControl::interrupt or
QueryControl::progress while it
runs. The control is generation-scoped: once the query finishes, it can no
longer affect a later query on the same connection.
Sourcepub fn database(&self) -> Database
pub fn database(&self) -> Database
Returns a shareable handle to the database backing this connection.
Use Database::connect to open further connections to the same database —
including, for :memory: databases, connections that observe the same data.
Source§impl Connection
impl Connection
Sourcepub fn register_aggregate_function<A: VAggregate>(
&mut self,
name: &str,
) -> Result<()>
pub fn register_aggregate_function<A: VAggregate>( &mut self, name: &str, ) -> Result<()>
Registers A as an aggregate function named name, with a default shared
state.
§Errors
Returns an error if name contains a NUL byte, a logical type cannot be
built, or DuckDB rejects the registration (e.g. a name conflict).
Sourcepub fn register_aggregate_function_with_state<A: VAggregate>(
&mut self,
name: &str,
shared: A::Shared,
) -> Result<()>
pub fn register_aggregate_function_with_state<A: VAggregate>( &mut self, name: &str, shared: A::Shared, ) -> Result<()>
Registers A as an aggregate function named name, with an explicit shared
registration state (available read-only to every callback).
§Errors
Sourcepub fn register_aggregate_function_set(
&mut self,
name: &str,
build: impl FnOnce(&mut AggregateSetBuilder<'_>) -> Result<()>,
) -> Result<()>
pub fn register_aggregate_function_set( &mut self, name: &str, build: impl FnOnce(&mut AggregateSetBuilder<'_>) -> Result<()>, ) -> Result<()>
Registers several VAggregate overloads under one SQL name as an aggregate
function set (DuckDB dispatches on argument types). Each (name-independent)
overload A_i is built with its own default shared state.
This takes a closure that adds overloads to a builder, so overloads of different Rust types can share one SQL name.
§Errors
As register_aggregate_function,
plus a conflict between two overloads in the set.
Source§impl Connection
impl Connection
Sourcepub fn register_cast_function<C: VCast>(&mut self) -> Result<()>
pub fn register_cast_function<C: VCast>(&mut self) -> Result<()>
Registers C as a custom cast, with a default shared state.
§Errors
Returns an error if a logical type cannot be built or DuckDB rejects the registration.
Source§impl Connection
impl Connection
Sourcepub fn register_scalar_function<S: VScalar>(&mut self, name: &str) -> Result<()>
pub fn register_scalar_function<S: VScalar>(&mut self, name: &str) -> Result<()>
Registers S as a scalar function named name, using S::State’s
default value as the shared state for every overload.
§Errors
Returns an error if name contains a NUL byte, a signature’s logical
type cannot be built, or DuckDB rejects the registration (e.g. a name
conflict).
Sourcepub fn register_scalar_function_with_state<S: VScalar>(
&mut self,
name: &str,
state: S::State,
) -> Result<()>
pub fn register_scalar_function_with_state<S: VScalar>( &mut self, name: &str, state: S::State, ) -> Result<()>
Registers S as a scalar function named name, with explicit shared
state. The state is cloned once per overload.
§Errors
Returns an error if name contains a NUL byte, a signature’s logical
type cannot be built, or DuckDB rejects the registration (e.g. a name
conflict).
Source§impl Connection
impl Connection
Sourcepub fn register_table_function<T: VTab>(&mut self, name: &str) -> Result<()>
pub fn register_table_function<T: VTab>(&mut self, name: &str) -> Result<()>
Registers T as a table function named name.
§Errors
Returns an error if name contains a NUL byte, a parameter’s logical
type cannot be built, or DuckDB rejects the registration (e.g. a name
conflict).
Sourcepub fn register_table_function_ext<T: VTabLocalInit>(
&mut self,
name: &str,
) -> Result<()>
pub fn register_table_function_ext<T: VTabLocalInit>( &mut self, name: &str, ) -> Result<()>
Registers T as a table function named name, additionally wiring its
per-worker-thread VTabLocalInit::local_init callback.
§Errors
Same as register_table_function.
Sourcepub fn register_table_function_with_extra_info<T: VTab, E: Send + Sync + 'static>(
&mut self,
name: &str,
extra_info: E,
) -> Result<()>
pub fn register_table_function_with_extra_info<T: VTab, E: Send + Sync + 'static>( &mut self, name: &str, extra_info: E, ) -> Result<()>
Registers T as a table function named name, sharing extra_info
read-only across every bind/init/func call for this function via
BindInfo::extra_info/InitInfo::extra_info/
TableFunctionInfo::extra_info.
§Errors
Same as register_table_function.