pub struct Database { /* private fields */ }Expand description
A handle onto one SQL database.
Send + Sync, cheap to share behind an Arc — see the module doc’s
Threading model section for what that concurrency contract does and
doesn’t buy a caller. Every operation is a blocking synchronous call;
see the module doc’s UI-thread discipline section before calling one
from the platform UI thread.
Implementations§
Source§impl Database
impl Database
Sourcepub fn open(name: &str) -> Result<Self, DatabaseError>
pub fn open(name: &str) -> Result<Self, DatabaseError>
Open (creating if absent) the named database at this crate’s
standard location, <data_dir>/databases/<name>.db
(frust_paths::data_dir), using the compiled default engine.
name is sanitized: it must be non-empty and contain no path
separator (/ or \) — see Self::open_with for choosing a
different engine, and Self::open_at for an explicit path.
The databases/ directory is deliberately shared by every frust app
on the machine (no per-binary app_stem component), which is also
why this crate does its own file-level read-through on macOS: if
<data_dir>/databases/<name>.db doesn’t exist but the same shape
under frust_paths::legacy_data_dir does, the legacy file is
opened where it already lives — nothing is migrated, copied, or
deleted. data_dir()’s own built-in macOS fallback probes
<base>/<app_stem> and so can never see this crate’s paths.
Platform locations:
- Android:
<Context.getFilesDir()>/databases/<name>.db. This directory is installed by the platform shell atnativeInitPlatformtime;Database::openmust run after this initialization completes (typically from app code, not from a static initializer). - iOS, macOS, Linux, Windows:
<data_dir>/databases/<name>.db, wheredata_diris resolved from environment variables (HOME,XDG_DATA_HOME,APPDATA, etc.).
§Errors
DatabaseError::Storage if name is invalid, no data directory
can be resolved (an unset HOME/APPDATA — this crate never
guesses a fallback that could silently write into the process’s
current directory, matching frust-shared-preferences’s own
FileStore::standard precedent), the databases directory can’t be
created, or (only once both engine features are compiled out) no
engine is available at all — that last case reports Storage naming
the missing feature, not DatabaseError::EngineUnavailable,
which no path here can construct: each Engine variant is gated on
the feature compiling its own backend, so an engine an
OpenOptions::engine caller can name is by construction compiled
in (see that variant’s own doc).
Sourcepub fn open_in_memory() -> Result<Self, DatabaseError>
pub fn open_in_memory() -> Result<Self, DatabaseError>
Open a private, non-shared in-memory database using the compiled default engine — gone once this handle is dropped.
§Errors
See Self::open.
Sourcepub fn open_at(path: &Path) -> Result<Self, DatabaseError>
pub fn open_at(path: &Path) -> Result<Self, DatabaseError>
Open (creating if absent) the database at an explicit path, using
the compiled default engine — bypasses Self::open’s standard
location and name sanitization entirely.
§Errors
See Self::open.
Sourcepub fn open_with(
name: &str,
options: OpenOptions,
) -> Result<Self, DatabaseError>
pub fn open_with( name: &str, options: OpenOptions, ) -> Result<Self, DatabaseError>
Open (creating if absent) the named database at this crate’s
standard location, with an explicit OpenOptions (currently:
engine selection).
§Errors
See Self::open.
Sourcepub fn execute(
&self,
sql: &str,
params: impl IntoParams,
) -> Result<u64, DatabaseError>
pub fn execute( &self, sql: &str, params: impl IntoParams, ) -> Result<u64, DatabaseError>
Run a non-row-returning statement (INSERT/UPDATE/DELETE/DDL),
returning the number of rows affected.
§Errors
DatabaseError::Sql if the engine rejects the statement;
DatabaseError::Reentrant if the calling thread is already inside
a Self::transaction closure on this same handle (use the
Transaction’s own execute there).
Sourcepub fn query(
&self,
sql: &str,
params: impl IntoParams,
) -> Result<Vec<Row>, DatabaseError>
pub fn query( &self, sql: &str, params: impl IntoParams, ) -> Result<Vec<Row>, DatabaseError>
Run a row-returning statement (SELECT), returning every resulting
row.
§Errors
DatabaseError::Sql if the engine rejects the statement;
DatabaseError::Reentrant if the calling thread is already inside
a Self::transaction closure on this same handle (use the
Transaction’s own query there).
Sourcepub fn transaction<T>(
&self,
f: impl FnOnce(&Transaction<'_>) -> Result<T, DatabaseError>,
) -> Result<T, DatabaseError>
pub fn transaction<T>( &self, f: impl FnOnce(&Transaction<'_>) -> Result<T, DatabaseError>, ) -> Result<T, DatabaseError>
Run f inside a BEGIN/COMMIT/ROLLBACK transaction — the same
plain SQL on both engines, run through the engine seam. Commits on
Ok, rolls back on Err, and returns whatever f returned (or its
error).
The transaction is rolled back on every path out that isn’t a
successful COMMIT — including the COMMIT statement itself failing
(SQLite’s deferred-constraint check runs there and leaves the
transaction open) and f panicking — so a call always leaves the
handle’s connection ready for the next one, never stranded
mid-transaction.
f must not call execute/query/transaction on the same
Database handle: the connection is already locked for the
transaction’s whole span, and re-entering it from the same thread is
refused with DatabaseError::Reentrant rather than deadlocking.
Use the Transaction handle f is given instead. Other threads
calling this handle meanwhile are unaffected — they queue, per the
module doc’s Threading model section.
§Errors
f’s own error, if it returns Err (after rolling back). A
BEGIN/COMMIT/ROLLBACK statement itself failing also surfaces
as DatabaseError::Sql (again after rolling back).
DatabaseError::Reentrant if the calling thread already holds this
handle’s connection.