Skip to main content

Database

Struct Database 

Source
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

Source

pub fn create(root: impl AsRef<Path>) -> Result<Self>

Create a fresh plaintext database at root.

Source

pub fn open(root: impl AsRef<Path>) -> Result<Self>

Open an existing plaintext database.

Source

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/15-credential-enforcement.md.

Source

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/15-credential-enforcement.md.

Source

pub fn visible_epoch(&self) -> Epoch

The current reader-visible epoch.

Source

pub fn catalog_snapshot(&self) -> Catalog

Clone the in-memory catalog (for diagnostics / tests).

Source

pub fn root(&self) -> &Path

The filesystem root this database was opened/created at.

Source

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.

Source

pub fn procedures(&self) -> Vec<StoredProcedure>

Source

pub fn procedure(&self, name: &str) -> Option<StoredProcedure>

Source

pub fn create_procedure( &self, procedure: StoredProcedure, ) -> Result<StoredProcedure>

Source

pub fn create_or_replace_procedure( &self, procedure: StoredProcedure, ) -> Result<StoredProcedure>

Source

pub fn drop_procedure(&self, name: &str) -> Result<()>

Source

pub fn users(&self) -> Vec<UserEntry>

List all catalog users (password hashes included — callers should not serialize them externally).

Source

pub fn roles(&self) -> Vec<RoleEntry>

List all catalog roles.

Source

pub fn create_user(&self, username: &str, password: &str) -> Result<UserEntry>

Create a new user with an Argon2id-hashed password.

Source

pub fn drop_user(&self, username: &str) -> Result<()>

Drop a user by username.

Source

pub fn alter_user_password( &self, username: &str, new_password: &str, ) -> Result<()>

Change a user’s password.

Source

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.

Source

pub fn set_user_admin(&self, username: &str, is_admin: bool) -> Result<()>

Grant admin privileges to a user (bypasses all permission checks).

Source

pub fn create_role(&self, name: &str) -> Result<RoleEntry>

Create a new role.

Source

pub fn drop_role(&self, name: &str) -> Result<()>

Drop a role by name.

Source

pub fn grant_role(&self, username: &str, role_name: &str) -> Result<()>

Grant a role to a user.

Source

pub fn revoke_role(&self, username: &str, role_name: &str) -> Result<()>

Revoke a role from a user.

Source

pub fn grant_permission( &self, role_name: &str, permission: Permission, ) -> Result<()>

Grant a permission to a role.

Source

pub fn revoke_permission( &self, role_name: &str, permission: Permission, ) -> Result<()>

Revoke a permission from a role.

Source

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.

Source

pub fn check_permission(&self, username: &str, permission: &Permission) -> bool

Check whether a user has a specific permission (via their roles).

Source

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.

Source

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.

Source

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.

Source

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/15-credential-enforcement.md.

Source

pub fn disable_auth(&self) -> Result<()>

Disable require_auth on this database, reverting it to credentialless mode. This is the recovery path — it requires the handle to already be open (and therefore already authenticated if require_auth was on).

After this call, the database can be reopened with plain open / open_encrypted without credentials. All existing users and roles are preserved in the catalog (so require_auth can be re-enabled without recreating them), but they are no longer consulted for enforcement.

For true offline recovery (when credentials are lost and no authenticated handle is available), the caller opens the database directly via the catalog file (filesystem access required) and calls this method — see the CLI’s auth disable-offline command.

See docs/15-credential-enforcement.md §4.7.

Source

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(())).

Source

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.

Source

pub fn triggers(&self) -> Vec<StoredTrigger>

Source

pub fn trigger(&self, name: &str) -> Option<StoredTrigger>

Source

pub fn create_trigger(&self, trigger: StoredTrigger) -> Result<StoredTrigger>

Source

pub fn create_or_replace_trigger( &self, trigger: StoredTrigger, ) -> Result<StoredTrigger>

Source

pub fn drop_trigger(&self, name: &str) -> Result<()>

Source

pub fn external_tables(&self) -> Vec<ExternalTableEntry>

Source

pub fn external_table(&self, name: &str) -> Option<ExternalTableEntry>

Source

pub fn create_external_table( &self, entry: ExternalTableEntry, ) -> Result<ExternalTableEntry>

Source

pub fn drop_external_table(&self, name: &str) -> Result<()>

Source

pub fn commit_external_table_state( &self, name: &str, state: &[u8], ) -> Result<Epoch>

Source

pub fn trigger_config(&self) -> TriggerConfig

Source

pub fn set_trigger_config(&self, config: TriggerConfig) -> Result<()>

Source

pub fn set_recursive_triggers(&self, recursive: bool)

Source

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.

Source

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).

Source

pub fn call_procedure( &self, name: &str, args: HashMap<String, Value>, ) -> Result<ProcedureCallResult>

Source

pub fn begin(&self) -> Transaction<'_>

Begin a new transaction reading at the current visible epoch.

Source

pub fn begin_with_isolation(&self, level: IsolationLevel) -> Transaction<'_>

Begin a transaction with a specific isolation level.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn snapshot_owned(&self) -> (Snapshot, OwnedSnapshotGuard)

Owned (clonable-handle) variant of Self::snapshot for cross-thread retention.

Source

pub fn table_names(&self) -> Vec<String>

Names of all live tables.

Source

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.

Source

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).

Source

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).

Source

pub fn table(&self, name: &str) -> Result<TableHandle>

Look up a live table by name.

Source

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.

Source

pub fn drop_table(&self, name: &str) -> Result<()>

Logically drop a table, logging the DDL through the shared WAL first.

Source

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).

Source

pub fn alter_column( &self, table_name: &str, column_name: &str, change: AlterColumn, ) -> Result<ColumnDef>

Source

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.

Source

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).

Source

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.

Source

pub fn doctor(&self) -> Result<Vec<u64>>

Quarantine unreadable tables (spec §16). Moves corrupt table dirs to _quarantine/<table_id>/, marks them dropped in the catalog, and unmounts them from the live table map so the DB still opens.

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.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.