pub struct Database<S> { /* private fields */ }Expand description
Owns the graph store and orchestrates parse → analyze → compile → execute.
Optionally drives a write-ahead log: when constructed via
Database::open_with_wal or Database::recover the database
holds an Arc<WalRecorder> that brackets every query with
begin → mutations → commit/abort → flush while the store write
lock is held, so the WAL order is exactly the in-memory commit order.
When constructed via Database::in_memory / Database::from_graph
the WAL handle is None and the engine pays only the existing
MutationRecorder::record null-pointer check per mutation.
Implementations§
Source§impl Database<InMemoryGraph>
impl Database<InMemoryGraph>
Sourcepub fn open_with_wal(wal_config: WalConfig) -> Result<Self>
pub fn open_with_wal(wal_config: WalConfig) -> Result<Self>
Open or create a WAL-enabled in-memory database from a fresh graph.
WalConfig::Disabled falls back to Database::in_memory.
Otherwise, opens the WAL directory, replays any committed
events into a fresh graph, installs a WalRecorder on the
graph, and returns a database ready to serve queries.
To restore from a snapshot in addition to the WAL, use
Database::recover instead.
Sourcepub fn open_named(
database_name: impl AsRef<str>,
options: DatabaseOpenOptions,
) -> Result<Self>
pub fn open_named( database_name: impl AsRef<str>, options: DatabaseOpenOptions, ) -> Result<Self>
Open or create a named portable database rooted under
options.database_dir.
The database name may be either a portable basename (app or
app.loradb) or a safe relative path (tenant/app). It is resolved
under options.database_dir before the WAL archive backend opens.
Sourcepub fn begin_transaction(
&self,
mode: TransactionMode,
) -> Result<Transaction<'_>>
pub fn begin_transaction( &self, mode: TransactionMode, ) -> Result<Transaction<'_>>
Start an explicit transaction.
Read-only transactions hold a shared read lock for their
lifetime; read-write transactions hold the write lock. The
staging clone is lazy — it only happens when a
TransactionMode::ReadWrite transaction sees its first
mutating statement. Materialized read-only statements run
straight against the live graph; tx-bound streams may still
clone so their cursors can own a stable view. ReadWrite
transactions that perform only materialized reads (or commit
empty) pay nothing for staging.
Sourcepub fn recover(
snapshot_path: impl AsRef<Path>,
wal_config: WalConfig,
) -> Result<Self>
pub fn recover( snapshot_path: impl AsRef<Path>, wal_config: WalConfig, ) -> Result<Self>
Restore from a snapshot file then replay any WAL records past it.
The snapshot’s wal_lsn (when set) becomes the replay fence —
events at or below that LSN are already represented in the
loaded snapshot and are skipped. A missing snapshot file is
treated as “fresh start” so operators can pass the same path
on every boot.
If the WAL contains a checkpoint marker newer than the
snapshot’s wal_lsn, a one-line warning is printed to stderr
— the snapshot is stale relative to a more recent checkpoint
the operator is presumably aware of. Recovery still proceeds
from the snapshot’s fence (replay re-applies every record
above it, which is conservative-correct); a tighter contract
is deferred to v2 because verifying that the marker’s
snapshot file actually exists and is loadable is a separate
observability concern.
Sourcepub fn stream(&self, query: &str) -> Result<QueryStream<'_>>
pub fn stream(&self, query: &str) -> Result<QueryStream<'_>>
Execute a query and return an owning row stream.
Sourcepub fn stream_with_params(
&self,
query: &str,
params: BTreeMap<String, LoraValue>,
) -> Result<QueryStream<'_>>
pub fn stream_with_params( &self, query: &str, params: BTreeMap<String, LoraValue>, ) -> Result<QueryStream<'_>>
Execute a parameterised query and return an owning row stream.
The compiled plan is classified at open time. Read-only
queries run directly off the live store and yield a
buffered cursor with plan-derived columns. Mutating queries
are routed through a hidden read-write Transaction:
full cursor exhaustion calls tx.commit (publishing staged
changes and replaying the tx-local WAL buffer); a premature
drop or any error from next_row calls tx.rollback so
the live store and the WAL stay untouched.
Sourcepub unsafe fn stream_with_params_owned(
self: &Arc<Self>,
query: &str,
params: BTreeMap<String, LoraValue>,
) -> Result<QueryStream<'static>>
pub unsafe fn stream_with_params_owned( self: &Arc<Self>, query: &str, params: BTreeMap<String, LoraValue>, ) -> Result<QueryStream<'static>>
Open a stream whose lifetime can be carried by an outer owner that
also retains an Arc<Database>.
§Safety
The returned stream may contain lock guards that borrow from the
database’s internal RwLock. The caller must keep this exact Arc
alive until the stream is dropped. This is intended for language
bindings that store both the Arc<Database> and the QueryStream in
the same opaque stream handle.
Source§impl<S> Database<S>where
S: GraphStorage + GraphStorageMut,
impl<S> Database<S>where
S: GraphStorage + GraphStorageMut,
Sourcepub fn from_graph(graph: S) -> Self
pub fn from_graph(graph: S) -> Self
Build a database by taking ownership of a bare graph store.
Sourcepub fn wal(&self) -> Option<&Arc<WalRecorder>>
pub fn wal(&self) -> Option<&Arc<WalRecorder>>
Handle to the installed WAL recorder, if any. Exposed for admin paths (checkpoint, truncate, observability) that need to drive the WAL outside the standard query lifecycle.
Sourcepub fn store(&self) -> &Arc<RwLock<S>>
pub fn store(&self) -> &Arc<RwLock<S>>
Handle to the underlying shared store — useful for callers that need to snapshot or share the graph across multiple databases.
Sourcepub fn parse(&self, query: &str) -> Result<Document>
pub fn parse(&self, query: &str) -> Result<Document>
Parse a query string into an AST without executing it.
Sourcepub fn execute(
&self,
query: &str,
options: Option<ExecuteOptions>,
) -> Result<QueryResult>
pub fn execute( &self, query: &str, options: Option<ExecuteOptions>, ) -> Result<QueryResult>
Execute a query and return its result.
Sourcepub fn execute_with_timeout(
&self,
query: &str,
options: Option<ExecuteOptions>,
timeout: Duration,
) -> Result<QueryResult>
pub fn execute_with_timeout( &self, query: &str, options: Option<ExecuteOptions>, timeout: Duration, ) -> Result<QueryResult>
Execute a query with a cooperative deadline. The timeout is checked at executor operator boundaries and hot scan loops; if it fires, the query returns an error and any WAL-backed mutating query is aborted through the existing failure path.
Sourcepub fn execute_with_params(
&self,
query: &str,
options: Option<ExecuteOptions>,
params: BTreeMap<String, LoraValue>,
) -> Result<QueryResult>
pub fn execute_with_params( &self, query: &str, options: Option<ExecuteOptions>, params: BTreeMap<String, LoraValue>, ) -> Result<QueryResult>
Execute a query with bound parameters.
When a WAL is attached the call is bracketed by a transaction:
recorder.arm()after analyze + compile (so a parse / semantic / compile error never opens a tx that has to be immediately aborted). Arming is cheap: no record is appended to the WAL yet, so a pure read query that completes here pays nothing for the WAL hot path.- The executor runs; every primitive mutation fires
MutationRecorder::record, which buffers events in memory. - On Ok,
recorder.commit()writesTxBegin, one batched mutation record, andTxCommitonly when mutations occurred; the surroundingrecorder.flush()runs only in that case so a read-only query never pays anfsync. - On Err,
recorder.abort()clears the pending batch. The engine has no rollback, so the in-memory state may already be partially mutated; the live handle is quarantined while durable recovery stays atomic because no committed batch was written. - The recorder’s poisoned flag is polled once (it also
surfaces background-flusher fsync failures from
SyncMode::Group). If set, the query fails loudly with the durability error so the caller can act on it; the WAL refuses further appends until the operator restarts the database, which recovers from the last consistent snapshot + WAL.
Sourcepub fn execute_with_params_timeout(
&self,
query: &str,
options: Option<ExecuteOptions>,
params: BTreeMap<String, LoraValue>,
timeout: Duration,
) -> Result<QueryResult>
pub fn execute_with_params_timeout( &self, query: &str, options: Option<ExecuteOptions>, params: BTreeMap<String, LoraValue>, timeout: Duration, ) -> Result<QueryResult>
Execute a parameterised query with a cooperative deadline.
Sourcepub fn execute_rows(&self, query: &str) -> Result<Vec<Row>>
pub fn execute_rows(&self, query: &str) -> Result<Vec<Row>>
Execute a query and return hydrated rows before final result-format projection.
Sourcepub fn execute_rows_with_params(
&self,
query: &str,
params: BTreeMap<String, LoraValue>,
) -> Result<Vec<Row>>
pub fn execute_rows_with_params( &self, query: &str, params: BTreeMap<String, LoraValue>, ) -> Result<Vec<Row>>
Execute a query with parameters and return hydrated rows before final result-format projection.
Sourcepub fn clear(&self)
pub fn clear(&self)
Drop every node and relationship.
When a WAL is attached, clear() is wrapped in arm/commit
so the MutationEvent::Clear fired by the store reaches the
log inside a transaction (without arming, the recorder would
poison itself on the first event). WAL failures here are
best-effort: the in-memory state is still cleared so the
caller’s contract holds, but the recorder’s poisoned flag
will surface to the next query.
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Number of nodes currently in the graph.
Sourcepub fn relationship_count(&self) -> usize
pub fn relationship_count(&self) -> usize
Number of relationships currently in the graph.
Sourcepub fn with_store<R>(&self, f: impl FnOnce(&S) -> R) -> R
pub fn with_store<R>(&self, f: impl FnOnce(&S) -> R) -> R
Run a closure with a shared borrow of the underlying store. Used by bindings to answer ad-hoc queries without locking the RwLock themselves.
Sourcepub fn with_store_mut<R>(&self, f: impl FnOnce(&mut S) -> R) -> R
pub fn with_store_mut<R>(&self, f: impl FnOnce(&mut S) -> R) -> R
Run a closure with an exclusive borrow of the underlying store. Reserved
for admin paths (restore, bulk load); regular mutation goes through
execute_with_params.
Source§impl<S> Database<S>
impl<S> Database<S>
Sourcepub fn save_snapshot_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
pub fn save_snapshot_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
Serialize the current graph state to the given path. Writes are
atomic: the payload goes to <path>.tmp, is fsync’d, and then
renamed over the target; a torn write can never leave a half-written
file at path. If any step before the rename fails, the stale
<path>.tmp is removed so a crashed save never leaks scratch files.
Holds a store read lock for the duration of the save so concurrent readers can proceed and writers wait behind a consistent snapshot.
Sourcepub fn load_snapshot_from(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
pub fn load_snapshot_from(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
Replace the current graph state with a snapshot loaded from path.
Holds the store write lock for the duration of the load; concurrent
queries block until restore completes.
Source§impl Database<InMemoryGraph>
impl Database<InMemoryGraph>
Sourcepub fn in_memory_from_snapshot(path: impl AsRef<Path>) -> Result<Self>
pub fn in_memory_from_snapshot(path: impl AsRef<Path>) -> Result<Self>
Convenience constructor: open (or create) an empty in-memory database
and immediately restore it from path. Errors if the file cannot be
opened or the snapshot is malformed.
Sourcepub fn checkpoint_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
pub fn checkpoint_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
Take a checkpoint: snapshot the current state with the WAL’s
durable_lsn stamped into the header, append a Checkpoint
marker to the WAL, then drop sealed segments at or below the
fence.
Errors with “checkpoint requires WAL enabled” when called on a
database constructed without a WAL — operators that just want
a fence-less dump should use [save_snapshot_to] instead.
The write-lock-held window covers snapshot serialization plus the
checkpoint marker append. Truncation runs after the rename
but still under the write lock; making it concurrent with queries
is a v2 concern (see docs/decisions/0004-wal.md).
Trait Implementations§
Source§impl<S> QueryRunner for Database<S>
impl<S> QueryRunner for Database<S>
fn execute( &self, query: &str, options: Option<ExecuteOptions>, ) -> Result<QueryResult>
Source§impl<S> SnapshotAdmin for Database<S>
impl<S> SnapshotAdmin for Database<S>
fn save_snapshot(&self, path: &Path) -> Result<SnapshotMeta>
fn load_snapshot(&self, path: &Path) -> Result<SnapshotMeta>
Source§impl WalAdmin for Database<InMemoryGraph>
impl WalAdmin for Database<InMemoryGraph>
Source§fn checkpoint(&self, path: &Path) -> Result<SnapshotMeta>
fn checkpoint(&self, path: &Path) -> Result<SnapshotMeta>
path. The snapshot’s header is stamped
with the WAL’s durable_lsn; older sealed segments are then
dropped.