pub struct Database { /* private fields */ }Expand description
Database represents a Stoolap database connection
This is the main entry point for using Stoolap. It wraps the storage engine and executor, providing a simple API for executing SQL queries.
§Thread Safety
Database is thread-safe and can be shared across threads via cloning. Each clone shares the same underlying storage engine.
§Examples
use stoolap::{Database, params};
// Open in-memory database
let db = Database::open("memory://")?;
// Create table
db.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)", ())?;
// Insert with parameters
db.execute("INSERT INTO users VALUES ($1, $2)", (1, "Alice"))?;
// Query
for row in db.query("SELECT * FROM users", ())? {
let row = row?;
println!("{}: {}", row.get::<i64>("id")?, row.get::<String>("name")?);
}Implementations§
Source§impl Database
impl Database
Sourcepub fn open(dsn: &str) -> Result<Self>
pub fn open(dsn: &str) -> Result<Self>
Open a database connection
The DSN (Data Source Name) specifies the database location:
memory://- In-memory database (data lost when closed)file:///path/to/db- Persistent database at the specified path
§Examples
// In-memory database
let db = Database::open("memory://")?;
// Persistent database
let db = Database::open("file:///tmp/mydb")?;§Engine Reuse
Opening the same DSN multiple times returns the same engine instance. This ensures consistency and prevents data corruption.
Sourcepub fn open_in_memory() -> Result<Self>
pub fn open_in_memory() -> Result<Self>
Open an in-memory database
This is a convenience method that creates a new in-memory database.
Each call creates a unique instance (unlike open("memory://") which
would share the same instance).
Sourcepub fn execute<P: Params>(&self, sql: &str, params: P) -> Result<i64>
pub fn execute<P: Params>(&self, sql: &str, params: P) -> Result<i64>
Execute a SQL statement
Use this for DDL (CREATE, DROP, ALTER) and DML (INSERT, UPDATE, DELETE) statements.
§Parameters
Parameters can be passed using:
- Empty tuple
()for no parameters - Tuple syntax
(1, "Alice", 30)for multiple parameters params!macroparams![1, "Alice", 30]
§Returns
Returns the number of rows affected for DML statements, or 0 for DDL.
§Examples
// DDL - no parameters
db.execute("CREATE TABLE users (id INTEGER, name TEXT)", ())?;
// DML with tuple parameters
db.execute("INSERT INTO users VALUES ($1, $2)", (1, "Alice"))?;
// DML with params! macro
db.execute("INSERT INTO users VALUES ($1, $2)", params![2, "Bob"])?;
// Update with mixed types
let affected = db.execute(
"UPDATE users SET name = $1 WHERE id = $2",
("Charlie", 1)
)?;Sourcepub fn query<P: Params>(&self, sql: &str, params: P) -> Result<Rows>
pub fn query<P: Params>(&self, sql: &str, params: P) -> Result<Rows>
Execute a query that returns rows
§Parameters
Parameters can be passed using:
- Empty tuple
()for no parameters - Tuple syntax
(value,)for single parameter (note trailing comma) - Tuple syntax
(1, "Alice")for multiple parameters params!macroparams![1, "Alice"]
§Examples
// Query all rows
for row in db.query("SELECT * FROM users", ())? {
let row = row?;
let id: i64 = row.get(0)?;
let name: String = row.get("name")?;
}
// Query with parameters
for row in db.query("SELECT * FROM users WHERE age > $1", (18,))? {
// ...
}
// Collect into Vec
let users: Vec<_> = db.query("SELECT * FROM users", ())?
.collect::<Result<Vec<_>, _>>()?;Sourcepub fn query_one<T: FromValue, P: Params>(
&self,
sql: &str,
params: P,
) -> Result<T>
pub fn query_one<T: FromValue, P: Params>( &self, sql: &str, params: P, ) -> Result<T>
Execute a query and return a single value
This is a convenience method for queries that return a single row with a single column. Returns an error if the query returns no rows.
§Examples
let count: i64 = db.query_one("SELECT COUNT(*) FROM users", ())?;
let name: String = db.query_one("SELECT name FROM users WHERE id = $1", (1,))?;Sourcepub fn query_opt<T: FromValue, P: Params>(
&self,
sql: &str,
params: P,
) -> Result<Option<T>>
pub fn query_opt<T: FromValue, P: Params>( &self, sql: &str, params: P, ) -> Result<Option<T>>
Sourcepub fn execute_with_timeout<P: Params>(
&self,
sql: &str,
params: P,
timeout_ms: u64,
) -> Result<i64>
pub fn execute_with_timeout<P: Params>( &self, sql: &str, params: P, timeout_ms: u64, ) -> Result<i64>
Sourcepub fn query_with_timeout<P: Params>(
&self,
sql: &str,
params: P,
timeout_ms: u64,
) -> Result<Rows>
pub fn query_with_timeout<P: Params>( &self, sql: &str, params: P, timeout_ms: u64, ) -> Result<Rows>
Sourcepub fn prepare(&self, sql: &str) -> Result<Statement>
pub fn prepare(&self, sql: &str) -> Result<Statement>
Prepare a SQL statement for repeated execution
Prepared statements are more efficient when executing the same query multiple times with different parameters.
§Examples
let stmt = db.prepare("SELECT * FROM users WHERE id = $1")?;
// Execute multiple times with different parameters
for id in 1..=10 {
for row in stmt.query((id,))? {
// ...
}
}Sourcepub fn execute_named(&self, sql: &str, params: NamedParams) -> Result<i64>
pub fn execute_named(&self, sql: &str, params: NamedParams) -> Result<i64>
Execute a statement with named parameters
Named parameters use the :name syntax in SQL queries.
§Examples
use stoolap::{Database, named_params};
let db = Database::open("memory://")?;
db.execute("CREATE TABLE users (id INTEGER, name TEXT, age INTEGER)", ())?;
// Insert with named params
db.execute_named(
"INSERT INTO users VALUES (:id, :name, :age)",
named_params!{ id: 1, name: "Alice", age: 30 }
)?;
// Update with named params
db.execute_named(
"UPDATE users SET name = :name WHERE id = :id",
named_params!{ id: 1, name: "Alicia" }
)?;Sourcepub fn query_named(&self, sql: &str, params: NamedParams) -> Result<Rows>
pub fn query_named(&self, sql: &str, params: NamedParams) -> Result<Rows>
Execute a query with named parameters
Named parameters use the :name syntax in SQL queries.
§Examples
use stoolap::{Database, named_params};
let db = Database::open("memory://")?;
db.execute("CREATE TABLE users (id INTEGER, name TEXT)", ())?;
db.execute("INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob')", ())?;
// Query with named params
for row in db.query_named(
"SELECT * FROM users WHERE name = :name",
named_params!{ name: "Alice" }
)? {
let row = row?;
println!("Found user: id={}", row.get::<i64>(0)?);
}Sourcepub fn query_one_named<T: FromValue>(
&self,
sql: &str,
params: NamedParams,
) -> Result<T>
pub fn query_one_named<T: FromValue>( &self, sql: &str, params: NamedParams, ) -> Result<T>
Sourcepub fn query_as<T: FromRow, P: Params>(
&self,
sql: &str,
params: P,
) -> Result<Vec<T>>
pub fn query_as<T: FromRow, P: Params>( &self, sql: &str, params: P, ) -> Result<Vec<T>>
Execute a query and map results to structs
This method executes a query and converts each row to a struct
that implements the FromRow trait.
§Examples
use stoolap::{Database, FromRow, ResultRow, Result};
struct User {
id: i64,
name: String,
}
impl FromRow for User {
fn from_row(row: &ResultRow) -> Result<Self> {
Ok(User {
id: row.get(0)?,
name: row.get(1)?,
})
}
}
let db = Database::open("memory://")?;
db.execute("CREATE TABLE users (id INTEGER, name TEXT)", ())?;
db.execute("INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob')", ())?;
// Query and map to structs
let users: Vec<User> = db.query_as("SELECT id, name FROM users", ())?;
assert_eq!(users.len(), 2);
assert_eq!(users[0].name, "Alice");Sourcepub fn query_as_named<T: FromRow>(
&self,
sql: &str,
params: NamedParams,
) -> Result<Vec<T>>
pub fn query_as_named<T: FromRow>( &self, sql: &str, params: NamedParams, ) -> Result<Vec<T>>
Execute a query with named parameters and map results to structs
§Examples
use stoolap::{Database, FromRow, ResultRow, Result, named_params};
struct Product {
id: i64,
name: String,
price: f64,
}
impl FromRow for Product {
fn from_row(row: &ResultRow) -> Result<Self> {
Ok(Product {
id: row.get(0)?,
name: row.get(1)?,
price: row.get(2)?,
})
}
}
let products: Vec<Product> = db.query_as_named(
"SELECT id, name, price FROM products WHERE price > :min_price",
named_params!{ min_price: 10.0 }
)?;Sourcepub fn begin(&self) -> Result<Transaction>
pub fn begin(&self) -> Result<Transaction>
Sourcepub fn begin_with_isolation(
&self,
isolation: IsolationLevel,
) -> Result<Transaction>
pub fn begin_with_isolation( &self, isolation: IsolationLevel, ) -> Result<Transaction>
Begin a new transaction with a specific isolation level
§Examples
use stoolap::IsolationLevel;
let tx = db.begin_with_isolation(IsolationLevel::Snapshot)?;
// All reads in this transaction see a consistent snapshot
tx.execute("UPDATE users SET balance = balance - 100 WHERE id = $1", (1,))?;
tx.commit()?;Sourcepub fn engine(&self) -> &Arc<MVCCEngine>
pub fn engine(&self) -> &Arc<MVCCEngine>
Get the underlying storage engine
This is primarily for advanced use cases and testing.
Sourcepub fn close(&self) -> Result<()>
pub fn close(&self) -> Result<()>
Close the database connection
This removes the database from the global registry and closes the engine, releasing the file lock immediately so another process can open the database.
Note: The engine is also closed automatically when all Database instances are dropped.
Sourcepub fn cached_plan(&self, sql: &str) -> Result<CachedPlanRef>
pub fn cached_plan(&self, sql: &str) -> Result<CachedPlanRef>
Get a cached plan for a SQL statement (parse once, execute many times).
Returns a CachedPlanRef that can be stored and passed to
execute_plan() / query_plan() for zero-lookup execution.
Sourcepub fn execute_plan<P: Params>(
&self,
plan: &CachedPlanRef,
params: P,
) -> Result<i64>
pub fn execute_plan<P: Params>( &self, plan: &CachedPlanRef, params: P, ) -> Result<i64>
Execute a pre-cached plan with positional parameters (no parsing, no cache lookup).
Sourcepub fn query_plan<P: Params>(
&self,
plan: &CachedPlanRef,
params: P,
) -> Result<Rows>
pub fn query_plan<P: Params>( &self, plan: &CachedPlanRef, params: P, ) -> Result<Rows>
Query using a pre-cached plan with positional parameters (no parsing, no cache lookup).
Sourcepub fn execute_named_plan(
&self,
plan: &CachedPlanRef,
params: NamedParams,
) -> Result<i64>
pub fn execute_named_plan( &self, plan: &CachedPlanRef, params: NamedParams, ) -> Result<i64>
Execute a pre-cached plan with named parameters (no parsing, no cache lookup).
Sourcepub fn query_named_plan(
&self,
plan: &CachedPlanRef,
params: NamedParams,
) -> Result<Rows>
pub fn query_named_plan( &self, plan: &CachedPlanRef, params: NamedParams, ) -> Result<Rows>
Query using a pre-cached plan with named parameters (no parsing, no cache lookup).
Sourcepub fn table_exists(&self, name: &str) -> Result<bool>
pub fn table_exists(&self, name: &str) -> Result<bool>
Check if a table exists
Sourcepub fn set_default_isolation_level(&self, level: IsolationLevel) -> Result<()>
pub fn set_default_isolation_level(&self, level: IsolationLevel) -> Result<()>
Set the default isolation level for new transactions
Sourcepub fn create_snapshot(&self) -> Result<()>
pub fn create_snapshot(&self) -> Result<()>
Create a point-in-time snapshot of the database
This creates snapshot files for each table that can be used to speed up database recovery. Instead of replaying the entire WAL, recovery can load the snapshot and only replay WAL entries after the snapshot.
Note: This is a no-op for in-memory databases.
Sourcepub fn semantic_cache_stats(&self) -> Result<SemanticCacheStatsSnapshot>
pub fn semantic_cache_stats(&self) -> Result<SemanticCacheStatsSnapshot>
Get semantic cache statistics
Returns statistics about the semantic query cache including hit rates, exact matches, and subsumption matches.
§Examples
let db = Database::open("memory://")?;
// ... execute some queries ...
let stats = db.semantic_cache_stats()?;
println!("Cache hits: {}", stats.hits);
println!("Subsumption hits: {}", stats.subsumption_hits);Sourcepub fn clear_semantic_cache(&self) -> Result<()>
pub fn clear_semantic_cache(&self) -> Result<()>
Clear the semantic cache
This clears all cached query results. Useful for testing or when you want to force queries to re-execute.
Trait Implementations§
Source§impl Clone for Database
impl Clone for Database
Source§fn clone(&self) -> Self
fn clone(&self) -> Self
Clone the database handle.
Each cloned handle has its own executor with independent transaction state, but shares the same underlying storage engine. This ensures proper transaction isolation - a BEGIN on one handle won’t affect reads on another handle.
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for Database
impl !RefUnwindSafe for Database
impl Send for Database
impl Sync for Database
impl Unpin for Database
impl UnsafeUnpin for Database
impl !UnwindSafe for Database
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> CompactArcDrop for T
impl<T> CompactArcDrop for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more