pub struct Database { /* private fields */ }Expand description
A multi-table database: one catalog, one epoch clock, shared caches, a
shared WAL, and a live map of name → Arc<Table>.
Implementations§
Source§impl Database
impl Database
Sourcepub fn create(root: impl AsRef<Path>) -> Result<Self>
pub fn create(root: impl AsRef<Path>) -> Result<Self>
Create a fresh plaintext database at root.
Sourcepub fn open_with_credentials(
root: impl AsRef<Path>,
username: &str,
password: &str,
) -> Result<Self>
pub fn open_with_credentials( root: impl AsRef<Path>, username: &str, password: &str, ) -> Result<Self>
Open an existing plaintext database that has require_auth = true,
verifying the supplied credentials up front and caching the resolved
[Principal] on the returned handle. Every subsequent operation will
be checked against that principal.
Returns MongrelError::AuthNotRequired if the database does not have
require_auth enabled — callers must pick the matching constructor for
the database’s mode. Returns MongrelError::InvalidCredentials on a
bad username/password.
See docs/auth-enforcement-spec.md.
Sourcepub fn create_with_credentials(
root: impl AsRef<Path>,
admin_username: &str,
admin_password: &str,
) -> Result<Self>
pub fn create_with_credentials( root: impl AsRef<Path>, admin_username: &str, admin_password: &str, ) -> Result<Self>
Create a fresh plaintext database with require_auth = true and a
single admin user. The returned handle is already authenticated as
that admin — every subsequent operation is checked against the admin
principal (which bypasses all permission checks via is_admin).
This is the bootstrap path: there is no window where the database requires auth but has no users.
See docs/auth-enforcement-spec.md.
Sourcepub fn visible_epoch(&self) -> Epoch
pub fn visible_epoch(&self) -> Epoch
The current reader-visible epoch.
Sourcepub fn catalog_snapshot(&self) -> Catalog
pub fn catalog_snapshot(&self) -> Catalog
Clone the in-memory catalog (for diagnostics / tests).
Sourcepub fn table_id(&self, name: &str) -> Result<u64>
pub fn table_id(&self, name: &str) -> Result<u64>
Resolve a table name → id (live tables only). pub(crate) so the transaction layer can stage by name.
pub fn procedures(&self) -> Vec<StoredProcedure>
pub fn procedure(&self, name: &str) -> Option<StoredProcedure>
pub fn create_procedure( &self, procedure: StoredProcedure, ) -> Result<StoredProcedure>
pub fn create_or_replace_procedure( &self, procedure: StoredProcedure, ) -> Result<StoredProcedure>
pub fn drop_procedure(&self, name: &str) -> Result<()>
Sourcepub fn users(&self) -> Vec<UserEntry>
pub fn users(&self) -> Vec<UserEntry>
List all catalog users (password hashes included — callers should not serialize them externally).
Sourcepub fn create_user(&self, username: &str, password: &str) -> Result<UserEntry>
pub fn create_user(&self, username: &str, password: &str) -> Result<UserEntry>
Create a new user with an Argon2id-hashed password.
Sourcepub fn alter_user_password(
&self,
username: &str,
new_password: &str,
) -> Result<()>
pub fn alter_user_password( &self, username: &str, new_password: &str, ) -> Result<()>
Change a user’s password.
Sourcepub fn verify_user(
&self,
username: &str,
password: &str,
) -> Result<Option<UserEntry>>
pub fn verify_user( &self, username: &str, password: &str, ) -> Result<Option<UserEntry>>
Verify credentials. Returns Some(entry) on success, None on
mismatch, Err on engine error.
Sourcepub fn set_user_admin(&self, username: &str, is_admin: bool) -> Result<()>
pub fn set_user_admin(&self, username: &str, is_admin: bool) -> Result<()>
Grant admin privileges to a user (bypasses all permission checks).
Sourcepub fn create_role(&self, name: &str) -> Result<RoleEntry>
pub fn create_role(&self, name: &str) -> Result<RoleEntry>
Create a new role.
Sourcepub fn grant_role(&self, username: &str, role_name: &str) -> Result<()>
pub fn grant_role(&self, username: &str, role_name: &str) -> Result<()>
Grant a role to a user.
Sourcepub fn revoke_role(&self, username: &str, role_name: &str) -> Result<()>
pub fn revoke_role(&self, username: &str, role_name: &str) -> Result<()>
Revoke a role from a user.
Sourcepub fn grant_permission(
&self,
role_name: &str,
permission: Permission,
) -> Result<()>
pub fn grant_permission( &self, role_name: &str, permission: Permission, ) -> Result<()>
Grant a permission to a role.
Sourcepub fn revoke_permission(
&self,
role_name: &str,
permission: Permission,
) -> Result<()>
pub fn revoke_permission( &self, role_name: &str, permission: Permission, ) -> Result<()>
Revoke a permission from a role.
Sourcepub fn resolve_principal(&self, username: &str) -> Option<Principal>
pub fn resolve_principal(&self, username: &str) -> Option<Principal>
Resolve a user into a crate::auth::Principal by collecting all
permissions from their roles. Returns None if the user doesn’t exist.
Sourcepub fn check_permission(&self, username: &str, permission: &Permission) -> bool
pub fn check_permission(&self, username: &str, permission: &Permission) -> bool
Check whether a user has a specific permission (via their roles).
Sourcepub fn require_auth_enabled(&self) -> bool
pub fn require_auth_enabled(&self) -> bool
Returns true if this database’s catalog has require_auth = true.
When true, every operation consults the cached [Principal] via
require.
Sourcepub fn principal(&self) -> Option<Principal>
pub fn principal(&self) -> Option<Principal>
A snapshot of the cached principal for this handle, if any. None for
databases opened without credentials (the default). Returns a clone
because the principal lives behind an RwLock.
Sourcepub fn refresh_principal(&self) -> Result<()>
pub fn refresh_principal(&self) -> Result<()>
Re-resolve the cached principal from the on-disk catalog. Long-lived
handles (e.g. a daemon) call this after a REVOKE or role change —
possibly made by a different handle to the same database — to pick up
the new effective permissions without re-verifying the password.
This reloads the catalog from disk first, so changes committed by other
handles (or other processes) are visible. The username is taken from
the existing cached principal; if the user has since been dropped,
returns MongrelError::InvalidCredentials.
No-op (returns Ok(())) on a credentialless database, or on a
credentialed database whose cached principal is None.
Sourcepub fn enable_auth(
&self,
admin_username: &str,
admin_password: &str,
) -> Result<()>
pub fn enable_auth( &self, admin_username: &str, admin_password: &str, ) -> Result<()>
Convert a credentialless database to a credentialed one: create the
first admin user, set require_auth = true, and cache the admin
principal on this handle so subsequent operations on the same handle
continue to work. After this call, the database can only be reopened
via open_with_credentials / open_encrypted_with_credentials.
Refuses if the database already has require_auth = true. This is
the conversion path for existing databases; for fresh databases,
create_with_credentials sets everything up atomically.
See docs/auth-enforcement-spec.md.
Sourcepub fn require(&self, perm: &Permission) -> Result<()>
pub fn require(&self, perm: &Permission) -> Result<()>
Enforcement check: if the catalog has require_auth = true, verify
that the cached principal satisfies perm. Called by every
enforcement point (DDL, admin, maintenance, and — in Phase 2 —
Table/Transaction/MongrelSession operations).
On a credentialless database this is a no-op (Ok(())).
Sourcepub fn require_table(&self, table: &str, perm: RequiredPermission) -> Result<()>
pub fn require_table(&self, table: &str, perm: RequiredPermission) -> Result<()>
Convenience: enforce a table-level permission (Select/Insert/
Update/Delete) by table name. Used by the Transaction layer and
other callers that know the operation kind + table name but don’t want
to construct the full Permission enum value themselves.
pub fn triggers(&self) -> Vec<StoredTrigger>
pub fn trigger(&self, name: &str) -> Option<StoredTrigger>
pub fn create_trigger(&self, trigger: StoredTrigger) -> Result<StoredTrigger>
pub fn create_or_replace_trigger( &self, trigger: StoredTrigger, ) -> Result<StoredTrigger>
pub fn drop_trigger(&self, name: &str) -> Result<()>
pub fn external_tables(&self) -> Vec<ExternalTableEntry>
pub fn external_table(&self, name: &str) -> Option<ExternalTableEntry>
pub fn create_external_table( &self, entry: ExternalTableEntry, ) -> Result<ExternalTableEntry>
pub fn drop_external_table(&self, name: &str) -> Result<()>
pub fn commit_external_table_state( &self, name: &str, state: &[u8], ) -> Result<Epoch>
pub fn trigger_config(&self) -> TriggerConfig
pub fn set_trigger_config(&self, config: TriggerConfig) -> Result<()>
pub fn set_recursive_triggers(&self, recursive: bool)
Sourcepub fn subscribe_changes(&self) -> Receiver<ChangeEvent>
pub fn subscribe_changes(&self) -> Receiver<ChangeEvent>
Subscribe to change-data-capture events. Returns a receiver that yields
ChangeEvents for every committed Put/Delete/NOTIFY.
Sourcepub fn notify(&self, channel: &str, message: Option<String>)
pub fn notify(&self, channel: &str, message: Option<String>)
Publish a notification message on a named channel. Reaches all active
subscribers (daemon /events, application listeners).
pub fn call_procedure( &self, name: &str, args: HashMap<String, Value>, ) -> Result<ProcedureCallResult>
Sourcepub fn begin(&self) -> Transaction<'_>
pub fn begin(&self) -> Transaction<'_>
Begin a new transaction reading at the current visible epoch.
Sourcepub fn begin_with_isolation(&self, level: IsolationLevel) -> Transaction<'_>
pub fn begin_with_isolation(&self, level: IsolationLevel) -> Transaction<'_>
Begin a transaction with a specific isolation level.
Sourcepub fn begin_with_external_trigger_bridge<'a>(
&'a self,
bridge: &'a dyn ExternalTriggerBridge,
) -> Transaction<'a>
pub fn begin_with_external_trigger_bridge<'a>( &'a self, bridge: &'a dyn ExternalTriggerBridge, ) -> Transaction<'a>
Begin a transaction whose trigger programs may route external-table DML through an application/query-layer module bridge.
Sourcepub fn transaction<T>(
&self,
f: impl FnOnce(&mut Transaction<'_>) -> Result<T>,
) -> Result<T>
pub fn transaction<T>( &self, f: impl FnOnce(&mut Transaction<'_>) -> Result<T>, ) -> Result<T>
Run f in a transaction; commit on Ok, rollback on Err.
Sourcepub fn transaction_with_external_trigger_bridge<'a, T>(
&'a self,
bridge: &'a dyn ExternalTriggerBridge,
f: impl FnOnce(&mut Transaction<'_>) -> Result<T>,
) -> Result<T>
pub fn transaction_with_external_trigger_bridge<'a, T>( &'a self, bridge: &'a dyn ExternalTriggerBridge, f: impl FnOnce(&mut Transaction<'_>) -> Result<T>, ) -> Result<T>
Run f in a transaction with an external-trigger bridge; commit on
Ok, rollback on Err.
Sourcepub fn snapshot(&self) -> (Snapshot, SnapshotGuard<'_>)
pub fn snapshot(&self) -> (Snapshot, SnapshotGuard<'_>)
Register a read snapshot at the current visible epoch and return it with a guard that retains it for GC until dropped.
Sourcepub fn snapshot_owned(&self) -> (Snapshot, OwnedSnapshotGuard)
pub fn snapshot_owned(&self) -> (Snapshot, OwnedSnapshotGuard)
Owned (clonable-handle) variant of Self::snapshot for cross-thread
retention.
Sourcepub fn table_names(&self) -> Vec<String>
pub fn table_names(&self) -> Vec<String>
Names of all live tables.
Sourcepub fn close(&self) -> Result<()>
pub fn close(&self) -> Result<()>
Best-effort flush-on-close (§4.4): force-flush every mounted table
that has pending writes to a .sr sorted run, so WAL segments can be
reaped on the next open. Call this as the last action before a
short-lived process (CLI, one-shot script) exits. The daemon does not
need this — its background auto-compactor handles run management.
Sourcepub fn compact(&self) -> Result<(usize, usize)>
pub fn compact(&self) -> Result<(usize, usize)>
Compact every mounted table: merge all sorted runs into one clean run
so query cost stays flat (single-run fast path) instead of growing
with run count. Tables with < 2 runs are skipped (no-op). Each table
is locked individually for its own compaction; snapshot retention is
honored by Table::compact. Returns (tables_compacted, tables_skipped).
Sourcepub fn compact_table(&self, name: &str) -> Result<bool>
pub fn compact_table(&self, name: &str) -> Result<bool>
Compact a single table by name. Returns Ok(true) if it was
compacted, Ok(false) if skipped (< 2 runs).
Sourcepub fn table(&self, name: &str) -> Result<TableHandle>
pub fn table(&self, name: &str) -> Result<TableHandle>
Look up a live table by name.
Sourcepub fn create_table(&self, name: &str, schema: Schema) -> Result<u64>
pub fn create_table(&self, name: &str, schema: Schema) -> Result<u64>
Create a new table. The DDL is first logged to the shared WAL
(Op::Ddl(CreateTable) + TxnCommit) and group-synced so it is durable
BEFORE the in-memory catalog and table map are mutated; the catalog
checkpoint is rewritten afterwards (spec §15, review fix #16). A reopen
that sees a stale catalog still recovers the table by replaying the Ddl.
Sourcepub fn drop_table(&self, name: &str) -> Result<()>
pub fn drop_table(&self, name: &str) -> Result<()>
Logically drop a table, logging the DDL through the shared WAL first.
Sourcepub fn rename_table(&self, name: &str, new_name: &str) -> Result<()>
pub fn rename_table(&self, name: &str, new_name: &str) -> Result<()>
Rename a live table. name must exist and new_name must not collide
with any live table; both checks run under ddl_lock so they are atomic
with the rename and with concurrent create_table existence checks (no
TOCTOU window). A no-op rename (name == new_name) succeeds without
side-effects. The rename is logged to the shared WAL as
DdlOp::RenameTable and recovered on reopen; the table_id, schema,
and on-disk layout are unchanged (the table is keyed by table_id, so
the in-memory object does not move — only the catalog name changes).
pub fn alter_column( &self, table_name: &str, column_name: &str, change: AlterColumn, ) -> Result<ColumnDef>
Sourcepub fn gc(&self) -> Result<usize>
pub fn gc(&self) -> Result<usize>
Retention-gated garbage collection (spec §6.4, §7.4, §16). Deletes:
- Dropped-table subdirs whose
at_epoch < min_active_snapshot. - Stale
_txn/dirs (aborted/crashed large-txn pending runs).
Returns the number of items reclaimed.
Sourcepub fn set_spill_threshold(&self, bytes: u64)
pub fn set_spill_threshold(&self, bytes: u64)
Set the per-table spill threshold (bytes). When a transaction’s staged bytes for a single table exceed this, the rows are written as a uniform-epoch pending run instead of streamed Put records (spec §8.5).
Sourcepub fn check(&self) -> Vec<CheckIssue>
pub fn check(&self) -> Vec<CheckIssue>
Verify multi-table integrity (spec §16). For every live table this:
authenticates the manifest; opens each RunRef’s file through
RunReader, which verifies the run footer
checksum and — for encrypted DBs — the keyed run-metadata MAC; checks each
run’s physical row count against its RunRef; flags RunRefs whose file
is missing (dangling) and .sr files on disk that no RunRef references
(orphan); and verifies flushed_epoch <= current_epoch. Returns the list
of issues found (empty = healthy). Orphans are warning-severity; all
other findings are error-severity (so Self::doctor quarantines them).
Cost: O(total run bytes) — the footer checksum is verified over each run’s full body, so this is an integrity tool, not a hot path.
Trait Implementations§
Source§impl Debug for Database
Manual Debug for Database — surfaces the diagnostics-relevant fields
(root, epoch, table count, encryption/auth state) without requiring every
internal type (Table, GroupCommit, broadcast sender, etc.) to impl Debug.
The raw field types carry locks, trait objects, and channels that have no
useful Debug output, so a hand-written impl is clearer than peppering
#[allow(dead_code)] skip attributes across two dozen fields.
impl Debug for Database
Manual Debug for Database — surfaces the diagnostics-relevant fields
(root, epoch, table count, encryption/auth state) without requiring every
internal type (Table, GroupCommit, broadcast sender, etc.) to impl Debug.
The raw field types carry locks, trait objects, and channels that have no
useful Debug output, so a hand-written impl is clearer than peppering
#[allow(dead_code)] skip attributes across two dozen fields.
Auto Trait Implementations§
impl !Freeze for Database
impl !RefUnwindSafe for Database
impl !UnwindSafe for Database
impl Send for Database
impl Sync for Database
impl Unpin for Database
impl UnsafeUnpin 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> 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