Skip to main content

Db

Struct Db 

Source
pub struct Db { /* private fields */ }
Expand description

An immutable value of a database at one basis transaction and time view.

§Memory

This value is fully resident. recorded holds every datom the value has seen — assertions and retractions alike, the whole history, not just the live facts — and a materialized view adds four covering indexes over it. A holder therefore pays, per datom:

  • one heap allocation for the datom itself, shared by handle with every index entry that refers to it, in every materialized view; plus
  • one encoded key per covering order the datom is in (always EAVT and AEVT, plus AVET for an indexed or unique attribute and VAET for a reference value), plus a pointer per entry.

So a fact is stored once however many orders and views index it. The keys are not free — a key embeds the encoded value, so a long string still appears once per covering order — but they are the ordering itself rather than a duplicate of the datom.

What is not bounded is history: nothing here is ever evicted, and a peer’s resident set grows with everything ever transacted rather than with the live database. A database whose history greatly exceeds its live set will be dominated by datoms no current query can reach.

§Cost of a time view

Materializing a view is O(recorded history), not O(the view’s size). Db::as_of folds the log up to its basis, Db::history folds all of it, and Db::since folds all of it and then filters. The result is cached in this value and shared by its clones — and views that select exactly the same datoms as an already-folded one share that fold rather than repeating it — but a distinct time view is a fresh fold over the whole history the first time it is read. Deriving many different as-of values, or re-deriving one from a fresh Db each time, pays that fold each time.

§How this differs from the design

docs/design/indexes-and-storage.md describes readers descending persistent segment trees and pulling only the segments a query touches, through a bounded cache. That is what the published format is being built toward; the inner tree levels that would let a reader seek without downloading an index are still future work. Until they land, a peer holds the whole database — and its whole history — in memory, and durable storage serves to reconstruct that state rather than to bound it.

Implementations§

Source§

impl Db

Source

pub fn new(schema: Schema) -> Self

Creates an empty database with the supplied schema.

The engine’s own attributes (bootstrap) are installed over schema, so every database understands :db/txInstant whether or not the caller’s schema mentions it.

Source

pub fn from_current_snapshot( basis_t: u64, schema: Schema, idents: Idents, interner: KeywordInterner, datoms: Vec<Datom>, ) -> Self

Creates a current database value from a published EAVT snapshot.

datoms must be the live facts at basis_t. Their original transaction ids are retained, but transactions before basis_t that no longer contribute a live fact are not reconstructed. This makes the value suitable for current queries and for applying the log tail; complete historical views still require replaying the full log.

:db/txInstant datoms are live facts (nothing retracts them), so a snapshot carries the transaction-time correspondence for every transaction it covers — unless it was published before the engine recorded instants as datoms, in which case instant-named views resolve only within the replayed tail.

Source

pub fn with_naming(self, idents: Idents, interner: KeywordInterner) -> Self

Attaches ident and keyword naming registries, returning the named value.

Source

pub const fn basis_t(&self) -> u64

Current transaction basis.

Source

pub const fn schema(&self) -> &Schema

Schema at this basis.

Source

pub fn idents(&self) -> &Idents

Ident registry.

Source

pub fn interner(&self) -> &KeywordInterner

Keyword interner used by keyword values in this database.

Source

pub const fn view(&self) -> DbView

The time view this value presents.

Source

pub fn recorded_datoms(&self) -> impl Iterator<Item = &Datom>

Every recorded assertion and retraction, in transaction order.

Source

pub fn recorded_len(&self) -> usize

Number of recorded assertions and retractions.

Source

pub fn recorded_since(&self, t: u64) -> impl Iterator<Item = &Datom>

The datoms transactions after t recorded, in the order they were recorded.

recorded is append-ordered, so the answer is a suffix: the scan walks back from the end and stops at the first datom at or before t, costing time proportional to the tail rather than to the whole history. This is what an indexing pass folds into the segments it last published ([corium_index::Segment::apply]) instead of rebuilding them.

A value opened from a published snapshot carries that snapshot’s live datoms as its prefix rather than a transaction-ordered history; every one of them is at or before the snapshot’s basis, so the same scan still stops at the boundary for any t at or after it.

Source

pub fn as_of(&self, t: u64) -> Self

Returns the as-of view at basis t: facts as they stood then.

Source

pub fn since(&self, t: u64) -> Self

Returns the since view: only live facts added after t.

Source

pub fn history(&self) -> Self

Returns the history view: all assertions and retractions ever.

Source

pub const fn instants(&self) -> &TxInstants

The t:db/txInstant correspondence recorded by this value.

Source

pub fn tx_instant(&self, t: u64) -> Option<i64>

The commit instant of transaction t, when this value has seen it.

Source

pub fn t_at_instant(&self, instant: i64) -> u64

The latest basis committed at or before instant (Unix milliseconds).

Zero when no known transaction is that old, so as-of an instant before the database existed is the empty value and since that instant is everything — the same interpretation Datomic gives out-of-range instants.

Source

pub fn as_of_instant(&self, instant: i64) -> Self

Returns the as-of view at wall-clock instant (Unix milliseconds): facts as they stood after the last transaction committed at or before it.

Source

pub fn since_instant(&self, instant: i64) -> Self

Returns the since view at wall-clock instant (Unix milliseconds): only live facts added after the last transaction committed at or before it.

Source

pub fn tx_range(&self, start: u64, end: Option<u64>) -> Vec<(u64, Vec<Datom>)>

Groups recorded datoms by transaction over the half-open range [start, end).

Source

pub fn datoms(&self) -> Vec<Datom>

Returns this view’s facts, deterministically ordered by EAVT.

Source

pub fn datoms_at(&self, order: IndexOrder) -> impl Iterator<Item = &Datom>

Iterates this view’s datoms in one index order.

AVET covers only indexed/unique attributes and VAET only reference values, mirroring Datomic’s covering-index composition.

Source

pub fn datoms_for_attribute(&self, a: AttrId) -> impl Iterator<Item = &Datom>

Iterates this view’s datoms for one attribute in AEVT order.

Unlike AVET, AEVT covers every installed attribute. Callers can use this as the fallback for attribute predicates that do not have AVET coverage.

Source

pub fn datoms_prefix<'a>( &'a self, order: IndexOrder, prefix: &'a [u8], ) -> impl Iterator<Item = &'a Datom>

Iterates datoms whose key in order starts with prefix.

Source

pub fn seek_datoms<'a>( &'a self, order: IndexOrder, start: &[u8], ) -> impl Iterator<Item = &'a Datom>

Iterates datoms in order starting from the first key at or after start.

Source

pub fn index_range<'a>( &'a self, a: AttrId, start: Option<&Value>, end: Option<&'a Value>, ) -> impl Iterator<Item = &'a Datom>

Iterates the AVET index for a over the value range [start, end).

Only indexed/unique attributes appear in AVET.

Source

pub fn values(&self, e: EntityId, a: AttrId) -> Vec<Value>

Current values for an entity/attribute pair.

Source

pub fn lookup(&self, a: AttrId, v: &Value) -> Option<EntityId>

Resolves a unique attribute/value pair to its entity.

Source

pub fn with_transaction(&self, t: u64, datoms: &[Datom]) -> Self

Applies a committed record, returning a new database value.

Only meaningful for the current view; time views are read-only.

A :db/txInstant assertion on the transaction entity — which every commit path materializes — is picked up as this transaction’s place on the wall clock.

Source

pub fn with_transaction_at( &self, t: u64, instant: i64, datoms: &[Datom], ) -> Self

Applies a committed record whose commit instant is known separately, materializing the :db/txInstant datom when datoms lacks one.

Replay paths use this so a log written before Corium recorded instants as datoms still yields instant-named views: the record’s timestamp field becomes the datom it would carry today.

Source

pub fn stats(&self) -> DbStats

Computes basic statistics over this view’s facts.

Source

pub fn planner_stats(&self) -> &PlannerStats

Planner statistics for this view, built lazily and cached.

Trait Implementations§

Source§

impl Clone for Db

Source§

fn clone(&self) -> Db

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Db

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for Db

Source§

fn default() -> Db

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Db

§

impl RefUnwindSafe for Db

§

impl Send for Db

§

impl Sync for Db

§

impl Unpin for Db

§

impl UnsafeUnpin for Db

§

impl UnwindSafe for Db

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.