Skip to main content

Connection

Struct Connection 

Source
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

Source

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.

Source

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

Source

pub fn open_in_memory() -> Result<Connection>

Opens an in-memory DuckDB connection.

§Errors

Returns an error if the connection cannot be established.

Source

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

Source

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)")?;
Source

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());
Source

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 Iterator impl on DuckResult.
  • INSERT / UPDATE / DELETE — check DuckResult::changes() for affected rows.
  • DDL (CREATE TABLE, DROP TABLE, etc.) — .changes() returns 0, 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);
Source

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])?;
Source

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.

Source

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.

Source

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).

Source

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.

Source

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).

Source

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.)

Source

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).

Source

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.

Source

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.

Source

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.

Source

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).

Source

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

Source

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.

Source

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.

Source

pub fn db(&self) -> &RawConnection

Returns a reference to the underlying RawConnection.

This provides access to low-level operations such as prepare.

Source

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.

Source

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.

Source

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

Source

pub fn register_aggregate_function<A: VAggregate>( &mut self, name: &str, ) -> Result<()>
where A::Shared: Default,

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).

Source

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

As register_aggregate_function.

Source

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

Source

pub fn register_cast_function<C: VCast>(&mut self) -> Result<()>
where C::Shared: Default,

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

pub fn register_cast_function_with_state<C: VCast>( &mut self, shared: C::Shared, ) -> Result<()>

Registers C as a custom cast, with an explicit shared state.

§Errors

As register_cast_function.

Source§

impl Connection

Source

pub fn register_scalar_function<S: VScalar>(&mut self, name: &str) -> Result<()>
where S::State: Default,

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).

Source

pub fn register_scalar_function_with_state<S: VScalar>( &mut self, name: &str, state: S::State, ) -> Result<()>
where S::State: Clone,

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

Source

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).

Source

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.

Source

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.

Trait Implementations§

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.