### DuckDB Rust Quickstart Example Source: https://github.com/duckdb/duckdb-rs/blob/main/crates/duckdb-loadable-macros/README.md Demonstrates connecting to an in-memory DuckDB database, creating a table, inserting data using various methods, and querying data into Rust structs. ```rust use duckdb::{params, Connection, Result}; struct Duck { id: i32, name: String, } fn main() -> Result<()> { let conn = Connection::open_in_memory()?; conn.execute( "CREATE TABLE ducks (id INTEGER PRIMARY KEY, name TEXT)", [], // empty list of parameters )?; conn.execute_batch( r#" INSERT INTO ducks (id, name) VALUES (1, 'Donald Duck'); INSERT INTO ducks (id, name) VALUES (2, 'Scrooge McDuck'); "#, )?; conn.execute( "INSERT INTO ducks (id, name) VALUES (?, ?)", params![3, "Darkwing Duck"], )?; let ducks = conn .prepare("FROM ducks")? .query_map([], |row| { Ok(Duck { id: row.get(0)?, name: row.get(1)?, }) })? .collect::>>()?; for duck in ducks { println!("{}) {}", duck.id, duck.name); } Ok(()) } ``` -------------------------------- ### Manage Transactions Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/README.md Demonstrates how to start a transaction, execute statements within it, and then commit the changes. Transactions ensure data consistency. ```rust let tx = conn.transaction()?; tx.execute("INSERT INTO users VALUES (?, ?)", params![4, "Dana"])?; tx.commit()?; ``` -------------------------------- ### Filter and Aggregate Arrow Batches (Conceptual) Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/arrow-batch.md Illustrates fetching Arrow RecordBatches and accessing columns for potential use with Arrow compute functions. This example shows the setup and conceptual application. ```rust use duckdb::Connection; use arrow::compute; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE metrics (timestamp INT, value FLOAT); INSERT INTO metrics VALUES (1, 10.5), (2, 20.3), (3, 15.8), (4, 25.1)" )?; let mut stmt = conn.prepare("SELECT value FROM metrics")?; let mut arrow = stmt.query_arrow([])?; if let Some(batch) = arrow.next() { let value_col = batch.column(0); // Arrow compute functions // let max = compute::max(value_col); // let sum = compute::sum(value_col); println!("Processed {} values", batch.num_rows()); } Ok(()) } ``` -------------------------------- ### Install LLVM/libclang on macOS Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Installs LLVM, which provides libclang, on macOS using the Homebrew package manager. ```shell brew install llvm ``` -------------------------------- ### Link against system DuckDB library (Linux example) Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Demonstrates setting environment variables to link against a pre-compiled DuckDB library on Linux. This involves downloading, unzipping, and exporting paths. ```shell wget https://github.com/duckdb/duckdb/releases/download/v1.5.4/libduckdb-linux-arm64.zip unzip libduckdb-linux-arm64.zip -d libduckdb export DUCKDB_LIB_DIR=$PWD/libduckdb export DUCKDB_INCLUDE_DIR=$DUCKDB_LIB_DIR export LD_LIBRARY_PATH=$DUCKDB_LIB_DIR cargo build --examples ``` -------------------------------- ### Install libclang on Debian/Ubuntu Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Installs the libclang development package required for the buildtime_bindgen feature on Debian-based Linux distributions. ```shell sudo apt-get update sudo apt-get install -y libclang-dev ``` -------------------------------- ### Manual DuckDB Binary Setup for macOS Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Steps to manually download and set up DuckDB binaries on macOS for use with duckdb-rs. Ensure the DUCKDB_LIB_DIR, DUCKDB_INCLUDE_DIR, and DYLD_FALLBACK_LIBRARY_PATH environment variables are correctly set. ```shell wget https://github.com/duckdb/duckdb/releases/download/v1.5.4/libduckdb-osx-universal.zip unzip libduckdb-osx-universal.zip -d libduckdb export DUCKDB_LIB_DIR=$PWD/libduckdb export DUCKDB_INCLUDE_DIR=$DUCKDB_LIB_DIR export DYLD_FALLBACK_LIBRARY_PATH=$DUCKDB_LIB_DIR cargo build --examples ``` -------------------------------- ### Retrieve Column Types from Prepared Statement Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md This example demonstrates how to use a prepared statement to query a table and retrieve the data types of its columns using the `column_type` method. Ensure the connection and statement are successfully created before calling this method. ```rust use duckdb::{Connection, types::Type}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE test (id INT, name TEXT)")?; let stmt = conn.prepare("SELECT * FROM test")?; assert_eq!(stmt.column_type(0), Type::Int); assert_eq!(stmt.column_type(1), Type::Text); Ok(()) } ``` -------------------------------- ### Start Explicit Transaction Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/transaction.md Begins an explicit transaction on the connection. The transaction is automatically rolled back on drop unless explicitly committed. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let mut conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE items (id INT, value INT)")?; { let tx = conn.transaction()?; tx.execute("INSERT INTO items VALUES (1, 100)", [])?; tx.execute("INSERT INTO items VALUES (2, 200)", [])?; tx.commit()?; // Explicit commit } Ok(()) } ``` -------------------------------- ### Insert Current Timestamp Example Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md Demonstrates inserting the current UTC timestamp into a DuckDB table using the 'chrono' integration. ```rust use duckdb::Connection; use chrono::Utc; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE events (timestamp TIMESTAMP)")?; let now = Utc::now(); conn.execute( "INSERT INTO events VALUES (?)", [&now] // Automatic ToSql conversion )?; Ok(()) } ``` -------------------------------- ### Add duckdb-rs with bundled-cmake and icu features Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Example of adding duckdb-rs with the experimental `bundled-cmake` feature and the `icu` extension, typically used with a Git checkout. ```toml [dependencies] duckdb = { git = "https://github.com/duckdb/duckdb-rs", branch = "main", features = ["bundled-cmake", "icu"] } ``` -------------------------------- ### Rust Type Conversions for SQL Insertion Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/params.md Demonstrates inserting various Rust data types into a DuckDB table, showcasing automatic conversion to corresponding SQL types. Includes examples for boolean, integer, float, text, blob, explicit NULL, and optional NULL values. ```rust use duckdb::{Connection, params, types::Null}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE all_types ( b BOOLEAN, i INT, f FLOAT, t TEXT, bl BLOB, n TEXT, o INT )" )?; conn.execute( "INSERT INTO all_types VALUES (?, ?, ?, ?, ?, ?, ?)", params![ true, // BOOLEAN 42i32, // INT 3.14, // FLOAT "text", // TEXT b"binary".to_vec(), // BLOB Null, // NULL (explicit) None::, // NULL (Option) ] )?; Ok(()) } ``` -------------------------------- ### Error Handling and Rollback in Rust Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/transaction.md Illustrates error handling for database operations within a transaction. The example shows how a primary key violation is caught and how an explicit rollback can be performed. ```Rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let mut conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE items (id INT PRIMARY KEY, value INT)" )?; let tx = conn.transaction()?; tx.execute("INSERT INTO items VALUES (1, 100)", [])?; // This will fail due to primary key constraint match tx.execute("INSERT INTO items VALUES (1, 200)", []) { Err(e) => { eprintln!("Insert failed: {}", e); // Transaction will rollback on drop } Ok(_) => { // Continue... } } // Explicit rollback on error tx.rollback()?; Ok(()) } ``` -------------------------------- ### Query with Named Parameters in WHERE Clause Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/params.md Shows how to use named parameters in the WHERE clause of a SELECT statement. This example filters products based on a minimum price and category, using `$min_price` and `$category`. ```rust use duckdb::{Connection, named_params}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE products (id INT, price FLOAT, category TEXT);\n INSERT INTO products VALUES (1, 29.99, 'Electronics'),\n (2, 15.99, 'Books'),\n (3, 199.99, 'Electronics')" )?; let min_price = 20.0; let cat = "Electronics"; let mut stmt = conn.prepare( "SELECT * FROM products WHERE price > $min_price AND category = $category" )?; let mut rows = stmt.query( named_params! { "min_price": min_price, "category": cat, } )?; while let Some(row) = rows.next()? { let id: i32 = row.get(0)?; let price: f64 = row.get(1)?; println!("Product {}: ${:.2}", id, price); } Ok(()) } ``` -------------------------------- ### Mapping Rows with MappedRows Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/row.md Use `query_map` and `MappedRows` to transform each row into a custom struct. This example demonstrates mapping database rows to a `Product` struct. ```rust use duckdb::{Connection, Result}; struct Product { id: i32, name: String, price: f64, } fn main() -> Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE products (id INT, name TEXT, price FLOAT); INSERT INTO products VALUES (1, 'Widget', 9.99), (2, 'Gadget', 19.99)" )?; let mut stmt = conn.prepare("SELECT * FROM products")?; let products: Vec = stmt.query_map([], |row| { Ok(Product { id: row.get(0)?, name: row.get(1)?, price: row.get(2)?, }) })? \ .collect::>>()? ; for p in products { println!("{}: ${:.2}", p.name, p.price); } Ok(()) } ``` -------------------------------- ### Add duckdb with bundled feature using cargo add (reiteration) Source: https://github.com/duckdb/duckdb-rs/blob/main/crates/duckdb-loadable-macros/README.md This command adds the duckdb crate with the 'bundled' feature, ensuring DuckDB is compiled from source. This is a repeat of a previous example, likely for emphasis or context within build notes. ```shell cargo add duckdb --features bundled ``` -------------------------------- ### Perform DuckDB Version Upgrade Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Execute the main upgrade script to update workspace crate versions, dependency pins, README examples, and DuckDB version references. This script also triggers the regeneration of bindings. ```shell ./upgrade.sh ``` -------------------------------- ### Perform Patch Release Upgrade Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Run the upgrade script with the --patch flag to update only crate versions, dependency pins, and README examples without changing the bundled DuckDB version or regenerating bindings. ```shell ./upgrade.sh --patch ``` -------------------------------- ### Open DuckDB Connections Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/README.md Demonstrates how to open an in-memory database, a file-based database, and a database with custom configuration settings. ```rust use duckdb::Connection; // In-memory let conn = Connection::open_in_memory()?; // File-based let conn = Connection::open("database.db")?; // With config let config = duckdb::Config::default().threads(4)?; let conn = Connection::open_with_flags("database.db", config)?; ``` -------------------------------- ### Execute Statement and Get Polars DataFrames Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Use `query_polars` to execute a statement and get an iterator over Polars DataFrames. This requires the `polars` feature to be enabled. ```rust pub fn query_polars(&mut self, params: P) -> Result> ``` ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE numbers (x INT); INSERT INTO numbers VALUES (1), (2), (3)" )?; let mut stmt = conn.prepare("SELECT * FROM numbers")?; let dfs: Vec<_> = stmt.query_polars([])?.collect(); println!("Got {} dataframes", dfs.len()); Ok(()) } ``` -------------------------------- ### Basic DuckDB Interaction in Rust Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Demonstrates creating an in-memory DuckDB database, inserting data using different methods (execute, execute_batch, params), and querying data with type-safe mappings. ```rust use duckdb::{params, Connection, Result}; struct Duck { id: i32, name: String, } fn main() -> Result<()> { let conn = Connection::open_in_memory()?; conn.execute( "CREATE TABLE ducks (id INTEGER PRIMARY KEY, name TEXT)", [], // empty list of parameters )?; conn.execute_batch( r#" INSERT INTO ducks (id, name) VALUES (1, 'Donald Duck'); INSERT INTO ducks (id, name) VALUES (2, 'Scrooge McDuck'); "#, )?; conn.execute( "INSERT INTO ducks (id, name) VALUES (?, ?)", params![3, "Darkwing Duck"], )?; let ducks = conn .prepare("FROM ducks")? .query_map([], |row| { Ok(Duck { id: row.get(0)?, name: row.get(1)?, }) })? .collect::>>()?; for duck in ducks { println!("{}) {}", duck.id, duck.name); } Ok(()) } ``` -------------------------------- ### AppendError Example Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/errors.md Demonstrates handling `AppendError` which occurs during data appending due to type mismatches or constraint violations. The example shows a duplicate key error. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE strict (id INT PRIMARY KEY, val INT NOT NULL)" )?; let mut appender = conn.appender("strict")?; match appender.append_row([1, 100]) { Ok(_) => { appender.append_row([1, 200])?; // Duplicate key appender.flush()?; } Err(duckdb::Error::AppendError) => { eprintln!("Append failed"); } _ => {} } Ok(()) } ``` -------------------------------- ### Chain Multiple DuckDB Configuration Options Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/configuration.md Demonstrates chaining various configuration methods to set up a DuckDB connection. This allows for setting threads, memory limits, access modes, and more in a single fluent call. ```rust use duckdb::{Connection, Config, config::{AccessMode, DefaultOrder, DefaultNullOrder}}; fn main() -> duckdb::Result<()> { let config = Config::default() .threads(4)? .max_memory("8GB")? .access_mode(AccessMode::ReadWrite)? .default_order(DefaultOrder::Asc)? .default_null_order(DefaultNullOrder::NullsLast)? .enable_external_access(true)? .custom_user_agent("MyApp/1.0")?; let conn = Connection::open_in_memory_with_flags(config)?; Ok(()) } ``` -------------------------------- ### Get All Column Names Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Retrieves a vector containing the names of all columns in the result set of a prepared statement. ```rust pub fn column_names(&self) -> Vec ``` -------------------------------- ### Configure DuckDB with Generic `with` Method Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/configuration.md Use the `with` method to set any DuckDB configuration option by key-value pair. Useful for advanced or new options not exposed directly. ```rust use duckdb::{Connection, Config}; fn main() -> duckdb::Result<()> { let config = Config::default() .with("memory_limit", "4GB")? .with("threads", "8")?; let conn = Connection::open_in_memory_with_flags(config)?; Ok(()) } ``` -------------------------------- ### Get Column Count Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Returns the total number of columns present in the result set of a prepared statement. ```rust pub fn column_count(&self) -> usize ``` -------------------------------- ### EnumType<'a> Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md Represents an ENUM column value, providing a method to get the string representation of the enum value. ```APIDOC ## EnumType<'a> ### Description Represents an ENUM column value. ### Methods - `value(&self) -> &'a str`: Returns the string representation of the enum value. ``` -------------------------------- ### Execute SQL Statements Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/README.md Shows how to execute Data Definition Language (DDL), Data Manipulation Language (DML), and query statements. Supports positional parameters for prepared statements. ```rust use duckdb::params; // DDL conn.execute_batch("CREATE TABLE users (id INT, name TEXT)")?; // DML conn.execute("INSERT INTO users VALUES (?, ?)", params![1, "Alice"])?; // Query (single row) let name: String = conn.query_row( "SELECT name FROM users WHERE id = ?", [1], |row| row.get(0) )?; // Query (multiple rows) let mut stmt = conn.prepare("SELECT * FROM users")?; let mut rows = stmt.query([])?; while let Some(row) = rows.next()? { println!("{}: {}", row.get::<_, i32>(0)?, row.get::<_, String>(1)?); } ``` -------------------------------- ### Configure DuckDB Connection with Options Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/INDEX.md Demonstrates setting various configuration options for a DuckDB connection, including threads, memory limits, access modes, and feature flags. Use this to customize your database instance for specific performance or feature needs. ```rust use duckdb::{Connection, Config, config::*}; let config = Config::default() .threads(8)? // Parallel threads .max_memory("4GB")? // Memory limit .access_mode(AccessMode::ReadWrite)? // R/W mode .enable_external_access(true)? // File/HTTP access .enable_autoload_extension(true)? // Auto-load extensions .with("custom_user_agent", "MyApp/1.0")?; // Custom settings let conn = Connection::open_in_memory_with_flags(config)?; ``` -------------------------------- ### Get Database Path Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/connection.md Retrieves the file path of a file-based DuckDB connection. Returns None for in-memory connections. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open("test.db")?; if let Some(path) = conn.path() { println!("Database: {}", path.display()); } Ok(()) } ``` -------------------------------- ### Get Column Names Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves a vector of all column names from a prepared statement. Useful for inspecting the schema of query results. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE test (a INT, b TEXT, c BOOLEAN)")?; let stmt = conn.prepare("SELECT * FROM test")?; let names = stmt.column_names(); assert_eq!(names, vec!["a", "b", "c"]); Ok(()) } ``` -------------------------------- ### Connection Pooling with r2d2 Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Demonstrates how to set up a connection pool using r2d2 for managing multiple threads accessing a DuckDB database. Each thread should acquire its own connection from the pool. ```rust use duckdb::{DuckdbConnectionManager, params}; let manager = DuckdbConnectionManager::file("file.db")?; let pool = r2d2::Pool::new(manager)?; // Each worker checks out its own connection from the pool. let conn = pool.get()?; conn.execute("INSERT INTO foo (bar) VALUES (?)", params![1])?; ``` -------------------------------- ### Insert with Multiple Positional Parameters Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/params.md Shows how to insert multiple values into an 'orders' table using the `params!` macro for customer ID, amount, and date. ```rust use duckdb::{Connection, params}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE orders (id INT, customer INT, amount FLOAT, date TEXT)" )?; let customer_id = 42; let amount = 99.99; let date = "2025-06-21"; conn.execute( "INSERT INTO orders VALUES (1, ?, ?, ?)", params![customer_id, amount, date] )?; Ok(()) } ``` -------------------------------- ### Get Column Index by Name Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Finds the 0-based index of a column given its name. Throws an error if the column name is not found. ```rust pub fn column_index(&self, name: &str) -> Result ``` -------------------------------- ### Build DuckDB from Source Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Clone the DuckDB repository and build a debug version of the C API library. This is the first step for local development involving C API changes. ```shell cd ~/github/ git clone git@github.com:duckdb/duckdb.git cd duckdb GEN=ninja make debug ``` -------------------------------- ### Get Column Metadata Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Retrieves metadata for each column in the result set of a prepared statement. Useful for inspecting schema information before or after execution. ```rust pub fn columns(&self) -> Vec> ``` ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE users (id INT, name TEXT); INSERT INTO users VALUES (1, 'Alice')" )?; let stmt = conn.prepare("SELECT id, name FROM users")?; for col in stmt.columns() { println!("Column: {} ({})", col.name(), col.decl_type().unwrap_or("?")); } Ok(()) } ``` -------------------------------- ### Prepare SQL Statement for Execution Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/connection.md Use `prepare` to create a reusable `Statement` object from a SQL string. This is efficient for executing the same query multiple times with different parameters. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE users (id INT, name TEXT)")?; let mut stmt = conn.prepare("INSERT INTO users VALUES (?, ?)")?; stmt.execute([1, "Alice"])?; stmt.execute([2, "Bob"])?; Ok(()) } ``` -------------------------------- ### with Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/configuration.md Sets any DuckDB configuration option by name and value. This is useful for advanced or newly introduced configuration options. ```APIDOC ## with ### Description Sets any DuckDB configuration option by name. Useful for advanced or new options. ### Method `with(mut self, key: impl AsRef, value: impl AsRef) -> Result` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **key** (`impl AsRef`) - Required - Configuration key name - **value** (`impl AsRef`) - Required - Configuration value ### Request Example ```rust use duckdb::{Connection, Config}; fn main() -> duckdb::Result<()> { let config = Config::default() .with("memory_limit", "4GB")? .with("threads", "8")?; let conn = Connection::open_in_memory_with_flags(config)?; Ok(()) } ``` ### Response #### Success Response (200) Configured `Config` for chaining #### Response Example None ### Throws `DuckDBFailure` if key or value is invalid ``` -------------------------------- ### Get Arrow Schema Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/arrow-batch.md Retrieves the Arrow schema for query results. Use this when you need to inspect the structure of the Arrow data before processing. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE test (id INT, name TEXT); INSERT INTO test VALUES (1, 'Alice')" )?; let mut stmt = conn.prepare("SELECT * FROM test")?; let arrow = stmt.query_arrow([])?; let schema = arrow.get_schema(); println!("Fields: {:?}", schema.fields()); Ok(()) } ``` -------------------------------- ### Prepared Statement Caching Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/INDEX.md Shows how to use prepared statement caching to improve performance by reusing prepared statements. The cache capacity can be configured. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE test (x INT)")?; // First call prepares and caches let stmt1 = conn.prepare_cached("SELECT * FROM test")?; // Subsequent calls reuse cached statement let stmt2 = conn.prepare_cached("SELECT * FROM test")?; conn.set_prepared_statement_cache_capacity(32); conn.flush_prepared_statement_cache(); Ok(()) } ``` -------------------------------- ### Get Column Type Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves the basic DuckDB type enumeration for a column specified by its index. Useful for simple type checks. ```rust use duckdb::{Connection, types::Type}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE mixed (flag BOOLEAN, count INT, ratio FLOAT)" )?; let stmt = conn.prepare("SELECT * FROM mixed")?; assert_eq!(stmt.column_type(0), Type::Boolean); assert_eq!(stmt.column_type(1), Type::Int); assert_eq!(stmt.column_type(2), Type::Float); Ok(()) } ``` -------------------------------- ### SQL to Rust Conversion with FromSql Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md Shows how to retrieve data from a DuckDB table and convert it into Rust types. Supports automatic type inference and handles SQL NULL values as Rust Option types. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE data (id INT, value DOUBLE); INSERT INTO data VALUES (1, 3.14)" )?; let mut stmt = conn.prepare("SELECT * FROM data")?; let mut rows = stmt.query([])?; if let Some(row) = rows.next()? { let id: i32 = row.get(0)?; let value: f64 = row.get(1)?; let maybe_extra: Option = row.get::<_, Option>(2)?; println!("ID: {}, Value: {}", id, value); } Ok(()) } ``` -------------------------------- ### Get Column Index by Name Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves the 0-based index of a column by its name (case-insensitive). Throws an error if the column name is not found. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE users (id INT, email TEXT)")?; let stmt = conn.prepare("SELECT id, email FROM users")?; let email_idx = stmt.column_index("email")?; println!("Email column index: {}", email_idx); Ok(()) } ``` -------------------------------- ### Test duckdb-rs with buildtime_bindgen Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Run tests for the main duckdb-rs crate using the exported library and header files. Ensure the DUCKDB_LIB_DIR and DUCKDB_INCLUDE_DIR environment variables are set. ```shell # Ensure environment variables are set export DUCKDB_LIB_DIR=~/duckdb-lib export DUCKDB_INCLUDE_DIR=~/duckdb-lib cd ~/github/duckdb-rs/ cargo test --features buildtime_bindgen -- --nocapture ``` -------------------------------- ### Get Column Count of a Row Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/row.md Retrieves the number of columns present in a given row. This is useful for understanding the structure of the data returned by a query. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE test (a INT, b TEXT, c BOOLEAN);\n INSERT INTO test VALUES (1, 'x', true)" )?; let mut stmt = conn.prepare("SELECT * FROM test")?; let mut rows = stmt.query([])?; if let Some(row) = rows.next()? { println!("Row has {} columns", row.column_count()); } Ok(()) } ``` -------------------------------- ### Test duckdb-rs with bundled feature Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Run tests for the main duckdb-rs crate using the bundled header file. This is a common testing configuration. ```shell cd ~/github/duckdb-rs cargo test --features bundled -- --nocapture ``` -------------------------------- ### Get Specific Column Name by Index Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves the name of a specific column using its 0-based index. Throws an error if the index is out of bounds. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE test (x INT, y TEXT)")?; let stmt = conn.prepare("SELECT x, y FROM test")?; let name0 = stmt.column_name(0)?; let name1 = stmt.column_name(1)?; println!("Columns: {}, {}", name0, name1); Ok(()) } ``` -------------------------------- ### Get Column Name Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves the name of a column from a prepared statement's result set. Use this when you need to identify columns by their names. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE users (id INT, name TEXT)")?; let stmt = conn.prepare("SELECT id, name FROM users")?; for col in stmt.columns() { println!("Column: {}", col.name()); } // Output: // Column: id // Column: name Ok(()) } ``` -------------------------------- ### Automatic DuckDB Binary Download for Testing Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Enables the build script to automatically download pre-built DuckDB binaries from GitHub Releases. This method links against the dynamic library and caches the downloaded archives. ```shell DUCKDB_DOWNLOAD_LIB=1 cargo test ``` -------------------------------- ### Test libduckdb-sys with bundled feature Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Run tests for the libduckdb-sys crate using the bundled header file. This is the default testing method in GitHub Actions. ```shell cd ~/github/duckdb-rs/crates/libduckdb-sys cargo test --features bundled ``` -------------------------------- ### Get Parameter Count of Prepared Statement Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Retrieves the total number of parameters present in a prepared SQL statement. This is useful for validating bindings before execution. ```rust pub fn parameter_count(&self) -> usize ``` -------------------------------- ### ListType<'a> Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md Represents a LIST column value with reference-based access to list elements. It provides methods to get the length of the list and retrieve elements by index. ```APIDOC ## ListType<'a> ### Description Represents a LIST column value with reference-based access to list elements. ### Methods - `len(&self) -> usize`: Returns the number of elements in the list. - `get(&self, idx: usize) -> Option>`: Retrieves an element at the specified index, returning `None` if the index is out of bounds. ``` -------------------------------- ### Insert using Array Slice for Positional Parameters Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/params.md Demonstrates inserting values into a 'test' table using an array slice `&[&dyn ToSql]` as an alternative to the `params!` macro. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE test (x INT, y INT)")?; // Array slice conn.execute("INSERT INTO test VALUES (?, ?)", &[&1, &2])?; Ok(()) } ``` -------------------------------- ### Enable Autoload Extension Configuration Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/configuration.md Configure whether to automatically load known DuckDB extensions. Use this when you need to control extension loading behavior. ```rust use duckdb::{Connection, Config}; fn main() -> duckdb::Result<()> { let config = Config::default() .enable_autoload_extension(false)?; let conn = Connection::open_in_memory_with_flags(config)?; Ok(()) } ``` -------------------------------- ### Rust to SQL Conversion with ToSql Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md Demonstrates inserting data into a DuckDB table using Rust values. Supports automatic conversion for primitive types and text, and explicit NULL values. ```rust use duckdb::{Connection, params, types::Null}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE users (name TEXT, age INT)")?; // Automatic conversion via ToSql conn.execute( "INSERT INTO users VALUES (?, ?)", params!["Alice", 30] )?; // Explicit NULL conn.execute( "INSERT INTO users VALUES (?, ?)", params!["Bob", Null] )?; Ok(()) } ``` -------------------------------- ### StructType<'a> Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/types.md Represents a STRUCT column value, allowing access to fields by name or index. It provides methods to get the number of fields and retrieve field values. ```APIDOC ## StructType<'a> ### Description Represents a STRUCT column value with named field access. ### Methods - `len(&self) -> usize`: Returns the number of fields in the struct. - `get_field(&self, name: &str) -> Option>`: Retrieves a field's value by its name, returning `None` if the field does not exist. - `get(&self, idx: usize) -> Option<(String, ValueRef<'a>)>`: Retrieves a field by its index, returning a tuple of the field name and its value, or `None` if the index is out of bounds. ``` -------------------------------- ### Enabling Dynamic Linking with vcpkg Source: https://github.com/duckdb/duckdb-rs/blob/main/crates/duckdb-loadable-macros/README.md When using vcpkg for dependency management, ensure dynamic linking is enabled by setting the VCPKGRS_DYNAMIC=1 environment variable before building. This is a specific configuration for vcpkg integration. ```shell VCPKGRS_DYNAMIC=1 ``` -------------------------------- ### Appending a Row Using AppenderParamsFromIter Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/appender.md This example demonstrates how to use appender_params_from_iter to append a row with dynamic values to a DuckDB table. Ensure the values match the table schema. ```rust use duckdb::{Connection, appender_params_from_iter}; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE dynamic (a INT, b TEXT)")?; let mut appender = conn.appender("dynamic")?; let values: Vec> = vec![ Box::new(42), Box::new("hello"), ]; appender.append_row(appender_params_from_iter(values.into_iter()))?; appender.flush()?; Ok(()) } ``` -------------------------------- ### Detect Memory Leaks in duckdb-rs Tests Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Run duckdb-rs tests with AddressSanitizer (ASan) enabled to detect memory leaks. Requires ASan setup and a symbolizer path. ```shell cd ~/github/duckdb-rs ASAN_OPTIONS=detect_leaks=1 ASAN_SYMBOLIZER_PATH=/usr/local/opt/llvm/bin/llvm-symbolizer cargo test --features bundled -- --nocapture ``` -------------------------------- ### Get Detailed Column Logical Type Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves a detailed logical type handle for a column, providing access to specific metadata like precision and scale for types such as DECIMAL. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE prices (amount DECIMAL(10, 2))" )?; let stmt = conn.prepare("SELECT * FROM prices")?; let logical_type = stmt.column_logical_type(0); // Access precision and scale for DECIMAL println!("Width: {}", logical_type.decimal_width()); println!("Scale: {}", logical_type.decimal_scale()); Ok(()) } ``` -------------------------------- ### Test libduckdb-sys with buildtime_bindgen Source: https://github.com/duckdb/duckdb-rs/blob/main/CONTRIBUTING.md Run tests for the libduckdb-sys crate using the exported library and header files. Ensure the DUCKDB_LIB_DIR and DUCKDB_INCLUDE_DIR environment variables are set. ```shell # Ensure environment variables are set export DUCKDB_LIB_DIR=~/duckdb-lib export DUCKDB_INCLUDE_DIR=~/duckdb-lib cd ~/github/duckdb-rs/crates/libduckdb-sys cargo test --features buildtime_bindgen ``` -------------------------------- ### prepare Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/connection.md Prepares a SQL statement for execution. The returned Statement can be executed multiple times with different parameters. ```APIDOC ## prepare ### Description Prepares a SQL statement for execution. The returned `Statement` can be executed multiple times with different parameters. ### Method Rust function call ### Parameters #### Path Parameters - **sql** (`&str`) - Required - SQL statement to prepare ### Request Example ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE users (id INT, name TEXT)")?; let mut stmt = conn.prepare("INSERT INTO users VALUES (?, ?)")?; stmt.execute([1, "Alice"])?; stmt.execute([2, "Bob"])?; Ok(()) } ``` ### Response #### Success Response - **Statement<'_>** - A prepared statement object that can be executed. #### Response Example (See Request Example for usage) ``` -------------------------------- ### Prepare and Cache Statement Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/connection.md Prepares an SQL statement and caches it for efficient reuse. Subsequent calls with identical SQL return the cached version. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE users (id INT)")?; // First call prepares and caches let stmt1 = conn.prepare_cached("SELECT * FROM users")?; // Second call returns cached statement let stmt2 = conn.prepare_cached("SELECT * FROM users")?; Ok(()) } ``` -------------------------------- ### Arrow Format Integration (Querying) Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/INDEX.md Demonstrates how to query data from DuckDB directly into Arrow format, supporting both buffered (all batches in memory) and streaming (one batch at a time) access. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE data (x INT, y FLOAT)")?; // Zero-copy Arrow access let mut stmt = conn.prepare("SELECT * FROM data")?; // Buffered (all batches in memory) let batches: Vec<_> = stmt.query_arrow([])? .filter(|b| b.num_rows() > 0) .collect(); // Or streaming (one batch at a time) use arrow::datatypes::{DataType, Field, Schema}; use std::sync::Arc; let schema = Arc::new(Schema::new(vec![ Field::new("x", DataType::Int32, false), Field::new("y", DataType::Float64, false), ])); let stream = stmt.stream_arrow([], schema)?; for batch in stream { println!("Batch: {} rows", batch.num_rows()); } Ok(()) } ``` -------------------------------- ### Accessing Row Columns as ValueRef Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/row.md Shows how to get a column value as a ValueRef without automatic type conversion, allowing for manual inspection or conversion. This is useful for dynamic type handling. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE mixed (val INT); INSERT INTO mixed VALUES (42)" )?; let mut stmt = conn.prepare("SELECT val FROM mixed")?; let mut rows = stmt.query([])?; if let Some(row) = rows.next()? { let val_ref = row.get_ref(0)?; match val_ref { duckdb::types::ValueRef::Int(i) => println!("Integer: {}", i), _ => println!("Other type"), } } Ok(()) } ``` -------------------------------- ### Get Declared Column Type Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/column.md Retrieves the declared type of a column as specified in the CREATE TABLE statement. Returns None for computed columns. Useful for understanding the schema of query results. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE data (id INT PRIMARY KEY, value FLOAT, summary TEXT);" )?; let stmt = conn.prepare("SELECT * FROM data")?; for col in stmt.columns() { println!("{}: {:?}", col.name(), col.decl_type()); } // Output: // id: Some("INT") // value: Some("FLOAT") // summary: Some("TEXT") Ok(()) } ``` -------------------------------- ### Insert using Direct Array for Positional Parameters Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/params.md Illustrates inserting values into a 'test' table using a direct array, offering a concise syntax for positional parameters without explicit macro usage. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch("CREATE TABLE test (x INT, y INT)")?; // Direct array conn.execute("INSERT INTO test VALUES (?, ?)", [5, 6])?; Ok(()) } ``` -------------------------------- ### Execute Statement and Get Arrow Batches Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/statement.md Use `query_arrow` to execute a statement and obtain an Arrow handle for zero-copy access to result batches. This is suitable when you need to process results in Arrow format. ```rust use duckdb::Connection; fn main() -> duckdb::Result<()> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE data (x INT, y INT); INSERT INTO data VALUES (1, 10), (2, 20)" )?; let mut stmt = conn.prepare("SELECT * FROM data")?; let batches: Vec<_> = stmt.query_arrow([])?.collect(); println!("Got {} batches", batches.len()); Ok(()) } ``` -------------------------------- ### Load DuckDB Extension Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/connection.md Dynamically loads a DuckDB extension by its name or path. Ensure the extension is available in the DuckDB environment. ```rust pub fn load_extension(&self, extension: &str) -> Result<()> ``` -------------------------------- ### Execute SQL Statements in DuckDB Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/INDEX.md Shows how to execute various SQL operations including DDL, DML, single-row queries, multi-row queries, Arrow format retrieval, and bulk inserts. ```rust use duckdb::{Connection, params}; let conn = Connection::open_in_memory()?; // DDL: Create table conn.execute_batch("CREATE TABLE users (id INT, name TEXT)")?; // DML: Insert data conn.execute( "INSERT INTO users VALUES (?, ?)", params![1, "Alice"] )?; // Query: Single row let name: String = conn.query_row( "SELECT name FROM users WHERE id = ?", [1], |row| row.get(0) )?; // Query: Multiple rows let mut stmt = conn.prepare("SELECT * FROM users")?; let mut rows = stmt.query([])?; while let Some(row) = rows.next()? { let id: i32 = row.get(0)?; let name: String = row.get(1)?; println!("{}: {}", id, name); } // Arrow format let batches: Vec<_> = conn .prepare("SELECT * FROM users")? .query_arrow([])? .collect(); // Bulk insert let mut appender = conn.appender("users")?; appender.append_rows(vec![[2, "Bob"], [3, "Charlie"]])?; appender.flush()?; ``` -------------------------------- ### Custom Error Handling with AndThenRows Source: https://github.com/duckdb/duckdb-rs/blob/main/_autodocs/api-reference/row.md Utilize `query_and_then` and `AndThenRows` to process rows with custom error types. This example defines a `ParseError` enum for handling potential data issues or database errors. ```rust use duckdb::Connection; #[derive(Debug)] enum ParseError { InvalidData(String), Database(duckdb::Error), } impl From for ParseError { fn from(e: duckdb::Error) -> Self { ParseError::Database(e) } } fn main() -> Result<(), ParseError> { let conn = Connection::open_in_memory()?; conn.execute_batch( "CREATE TABLE numbers (id INT, value INT); INSERT INTO numbers VALUES (1, 10), (2, 20)" )?; let mut stmt = conn.prepare("SELECT value FROM numbers")?; let values: Vec = stmt.query_and_then([], |row| { let val: i32 = row.get(0)?; if val < 0 { Err(ParseError::InvalidData("Negative value".to_string())) } else { Ok(val) } })? \ .collect::, _>>()?; println!("Values: {:?}", values); Ok(()) } ``` -------------------------------- ### Loading ICU Extension at Runtime Source: https://github.com/duckdb/duckdb-rs/blob/main/README.md Demonstrates how to load the ICU extension at runtime within a DuckDB connection. This is necessary when the bundled feature does not include ICU due to package size limits. ```rust conn.execute_batch("INSTALL icu; LOAD icu;")?; ```