pub struct Database { /* private fields */ }Expand description
Embedded SPG database handle. Owns an Engine + provides
ergonomic wrappers around execute and query. Drops the
engine on Drop — no WAL flush / fsync, because v6.10.3
is in-memory only.
Implementations§
Source§impl Database
impl Database
Sourcepub fn open_in_memory() -> Self
pub fn open_in_memory() -> Self
Open a fresh in-memory database. No WAL, no catalog snapshot on disk — perfect for tests + short-lived CLI tools.
Sourcepub fn open_path(db_path: impl AsRef<Path>) -> Result<Self, EngineError>
pub fn open_path(db_path: impl AsRef<Path>) -> Result<Self, EngineError>
v7.1 — Open or create a persistent database backed by
the file at db_path. The WAL lives at db_path +
“.wal” (e.g. ./data/spg.db → ./data/spg.db.wal). Boot
path:
- If
db_pathexists, restore the catalog snapshot. - If the WAL exists, replay every record into the
restored engine — the same recovery story
spg-serveruses. - Open the WAL in append+sync mode so subsequent
execute()writes durably commit (one fsync per mutation).
Drop writes a final catalog snapshot + truncates the
WAL — operators that need a sync barrier at a specific
point use checkpoint() explicitly.
Sourcepub fn freeze_oldest_to_cold(
&mut self,
table_name: &str,
index_name: &str,
max_rows: usize,
) -> Result<FreezeReport, EngineError>
pub fn freeze_oldest_to_cold( &mut self, table_name: &str, index_name: &str, max_rows: usize, ) -> Result<FreezeReport, EngineError>
v7.1.4 — freeze the oldest max_rows of table_name’s
hot tier into a brand-new cold-tier segment + persist
it to disk. Same semantics as spg-server’s freezer
thread; embedded just runs the freeze synchronously on
the caller’s thread. Persistence + manifest update
happen as part of the next checkpoint() (or on Drop).
Sourcepub fn set_checkpoint_threshold_bytes(&mut self, bytes: u64)
pub fn set_checkpoint_threshold_bytes(&mut self, bytes: u64)
v7.1 — override the auto-checkpoint WAL-size ceiling for
this Database instance. Default is
SPG_EMBEDDED_CHECKPOINT_BYTES env (4 MiB if unset); the
setter wins. No-op when the database is in-memory.
Sourcepub fn checkpoint(&mut self) -> Result<(), EngineError>
pub fn checkpoint(&mut self) -> Result<(), EngineError>
v7.1 — flush a fresh catalog snapshot to db_path and
truncate the WAL. Idempotent; cheap when nothing has
happened since the last checkpoint. No-op when the
database is in-memory (no db_path configured).
Called automatically when:
- the WAL grows past
SPG_EMBEDDED_CHECKPOINT_BYTES(default 4 MiB) at the end of anexecute(), and Dropruns (best-effort; checkpoint failure on drop is logged to stderr).
Sourcepub fn restore(snapshot: &[u8]) -> Result<Self, EngineError>
pub fn restore(snapshot: &[u8]) -> Result<Self, EngineError>
Restore a database from a previously-captured catalog
snapshot. Pairs with Database::snapshot() for
round-tripping in-memory state without going through
the spg-server WAL.
Sourcepub fn snapshot(&self) -> Vec<u8> ⓘ
pub fn snapshot(&self) -> Vec<u8> ⓘ
Take a catalog snapshot suitable for Database::restore.
The bytes are SPG’s canonical catalog envelope (FILE_MAGIC
- version + payload); round-trips through every released SPG version per the STABILITY contract.
Sourcepub fn execute(&mut self, sql: &str) -> Result<QueryResult, EngineError>
pub fn execute(&mut self, sql: &str) -> Result<QueryResult, EngineError>
Execute a SQL statement and return the engine’s
QueryResult verbatim. Pass-through for callers that
want to keep PG-flavoured column/row metadata.
v7.1 — when the database was opened via open_path,
successful mutations are appended to the WAL + fsynced
before the call returns. A subsequent process crash will
recover state up to the last successful return from
execute(). Read-only statements (SELECT / SHOW /
EXPLAIN / BEGIN-COMMIT-ROLLBACK / CHECKPOINT / COMPACT
etc.) skip the WAL entirely.
Sourcepub fn query_typed<T: FromSpgRow>(
&mut self,
sql: &str,
) -> Result<Vec<T>, EngineError>
pub fn query_typed<T: FromSpgRow>( &mut self, sql: &str, ) -> Result<Vec<T>, EngineError>
v7.3.0 — typed-row variant of Database::query. Each
row decodes into a T: FromSpgRow so callers don’t
pattern-match on Value themselves. Use spg_row! to
generate the impl, or write it by hand.
Sourcepub fn query(&mut self, sql: &str) -> Result<Vec<Vec<Value>>, EngineError>
pub fn query(&mut self, sql: &str) -> Result<Vec<Vec<Value>>, EngineError>
Run a SELECT and return rows as a Vec<Vec<Value>> —
strips the column-schema metadata for read-side
ergonomics. Errors on non-Rows results (DML / DDL
statements should go through execute instead).
Sourcepub const fn engine(&self) -> &Engine
pub const fn engine(&self) -> &Engine
Borrow the underlying engine. Escape hatch for callers
that need access to spg-engine APIs not yet surfaced
here (transactions, EXPLAIN ANALYZE, etc.).
Sourcepub const fn engine_mut(&mut self) -> &mut Engine
pub const fn engine_mut(&mut self) -> &mut Engine
Mutable borrow of the underlying engine. Same intent as
engine() but for write-side APIs (e.g. inserting
directly through Catalog::insert for high-throughput
bulk loads that bypass SQL parsing).
Sourcepub fn with_transaction<R, F>(&mut self, body: F) -> Result<R, EngineError>
pub fn with_transaction<R, F>(&mut self, body: F) -> Result<R, EngineError>
v7.2.0 — run body inside an implicit BEGIN /
COMMIT pair. The body receives &mut Database so it
can execute() / query() like any other code path;
the only difference is that every write in the body
lands inside one transaction, and a returned Err from
the body triggers ROLLBACK before the error propagates.
Nested calls are not supported — SPG’s transaction
model is single-writer with explicit BEGIN /
COMMIT / ROLLBACK, and a nested with_transaction
would hit EngineError::Unsupported("nested transaction") at the inner BEGIN.
Source§impl Database
impl Database
Sourcepub fn cold_segment_count(&self) -> usize
pub fn cold_segment_count(&self) -> usize
v7.7.4 — observe the catalog’s cold-segment count. Useful for tests + dashboards that want to verify auto-compaction is firing.
Sourcepub fn metrics(&self) -> EmbeddedMetrics
pub fn metrics(&self) -> EmbeddedMetrics
v7.7.5 — observability snapshot. Returns a point-in-time
view of the engine + persistence counters. Cheap (no
locks beyond the existing &self borrow), so safe to
call from a hot metrics-scrape path.
Fields mirror the operational dashboard
spg-server exposes,
minus the network counters that don’t apply to embedded.
Sourcepub fn spawn_background_freezer(
db: Arc<Mutex<Database>>,
opts: FreezerOptions,
) -> FreezerHandle
pub fn spawn_background_freezer( db: Arc<Mutex<Database>>, opts: FreezerOptions, ) -> FreezerHandle
v7.2.1 — spawn a background thread that periodically
runs freeze_oldest_to_cold when the catalog-wide hot
tier exceeds opts.hot_tier_bytes. The Arc<Mutex<_>>
pattern matches the v7.2 sharing story: callers wrap
their Database in Arc::new(Mutex::new(db)) once,
then clone the Arc for the worker + for foreground
access. Return value is a handle whose Drop joins the
worker.
Picks the freeze target the same way spg-server’s
freezer does: largest-hot_bytes user table with at
least one BTree integer-PK index. Tables without a
freezable index are skipped silently.