Skip to main content

Collection

Struct Collection 

Source
pub struct Collection<'tx, T: Document> { /* private fields */ }
Expand description

Typed handle to a collection.

Construct via crate::WriteTxn::collection (lazy-create) or crate::ReadTxn::collection (read-only; errors if absent).

All methods take &self because the underlying state lives behind mutexes on the parent transaction; the handle itself is stateless beyond the descriptor it caches.

Implementations§

Source§

impl<'tx, T: Document> Collection<'tx, T>

Source

pub fn descriptor(&self) -> &CollectionDescriptor

Cached descriptor (collection_id, primary_root, type_version, next_id at handle-open time).

Source

pub fn insert(&self, doc: T) -> Result<Id>

Insert doc. Returns the freshly-allocated Id.

§Errors
  • Error::ReadOnly if the handle is read-only.
  • Pager / catalog / codec errors propagated.
Source

pub fn get(&self, id: Id) -> Result<Option<T>>

Fetch the document at id.

On the write side this consults the pager (sees pending writes in the current txn). On the read side it consults the snapshot’s frozen view.

§Lazy migration (M10 #84)

If the on-disk record was written by an older Document::VERSION than the current T::VERSION, the codec walks the stored bytes through the schema registered for that version (see T::historical_schemas()) and dispatches the resulting structured Dynamic through T::migrate. The migrated bytes are NOT written back to disk. The next Collection::get re-reads the same v(n) bytes and re-runs migration. Only a subsequent Collection::update / Collection::upsert writes the document back, at which point the on-disk header records T::VERSION.

This contract is what allows mixed-version reads to scale: a 10⁹-doc collection does not need to be batch-rewritten on schema upgrade. Power-of-ten Rule 7: every “migration ran” path returns the migrated T; no implicit write-back.

§Errors

Pager / B-tree / codec errors propagated. In particular:

Source

pub fn update<F>(&self, id: Id, f: F) -> Result<()>
where F: FnOnce(&mut T),

Apply f to the document at id, writing the mutated value back.

§Errors
Source

pub fn delete(&self, id: Id) -> Result<bool>

Delete the document at id. Returns true if it existed.

§Errors
  • Error::ReadOnly on a read-side handle.
  • Pager / catalog errors propagated.
Source

pub fn upsert(&self, id: Id, doc: T) -> Result<()>

Insert-or-replace doc at id.

§Errors
  • Error::ReadOnly on a read-side handle.
  • Pager / catalog / codec errors propagated.
Source

pub fn find_unique( &self, index_name: &str, key: impl Into<Dynamic>, ) -> Result<Option<T>>

Look up the single document whose index_name key matches key under a Unique index.

Errors with Error::IndexNotUnique if index_name resolves to a non-unique index — find_unique is only defined on Unique indexes. For Standard / Each / Composite use Self::lookup (which returns an iterator).

Snapshot-aware: on a write-side handle the lookup sees the current txn’s pending writes; on a read-side handle it sees the snapshot’s frozen view.

§Errors
Source

pub fn lookup( &self, index_name: &str, key: impl Into<Dynamic>, ) -> Result<Box<dyn Iterator<Item = Result<T>> + Send + 'static>>
where T: Send + 'static,

Yield every document whose index_name key matches key. Works on Standard / Unique / Each indexes. Returns Err(Error::IndexKindMismatch)-style guidance for Composite (use Self::index_range for tuple-shaped keys).

The same document is yielded at most once even if it owns multiple matching entries — Each indexes can encode the same id under multiple element keys; we de-dup on emit.

§Errors
  • Error::IndexNotFound if index_name is unknown / dropped.
  • Pager / B-tree / codec errors propagated.
Source

pub fn index_range( &self, index_name: &str, range: impl RangeBounds<Vec<u8>>, ) -> Result<Box<dyn Iterator<Item = Result<(Vec<u8>, T)>> + Send + 'static>>
where T: Send + 'static,

Yield (encoded_key, doc) pairs whose encoded key bytes fall within range. The range bounds are bytes (the caller is responsible for producing them through encode_field / encode_index_key); this keeps the signature general for Composite “starts-with” scans.

For non-Unique kinds (Standard / Each / Composite) the bounds are widened internally so a user-facing Included(x)..=Included(x) range matches every entry whose user-key equals x even though the underlying B-tree key carries an id_be8 suffix (see docs/format.md § Index key encoding § Range-bound widening (non-Unique kinds)).

§Errors
  • Error::IndexNotFound if index_name is unknown / dropped.
  • Pager / B-tree / codec errors propagated.
Source

pub fn count_all(&self) -> Result<u64>

Count every entry in the primary tree WITHOUT decoding the documents. Used by the M8 crate::Query::count no-decode fast path; the iterator visits leaf pages and counts entries rather than running each through postcard.

Power-of-ten Rule 2: bounded by the B+tree’s MAX_RANGE_NODES budget (inherited from BTree::range).

§Errors

Pager / B-tree errors propagated.

Source

pub fn count_index_range( &self, index_name: &str, range: impl RangeBounds<Vec<u8>>, ) -> Result<u64>

Count every entry whose encoded key falls inside range on the named index’s B-tree, WITHOUT decoding any document. M8 fast path for crate::Query::count when the source is an index_range.

Returns the number of index B-tree entries — for an Each index that may exceed the document count (one doc emits multiple entries); for other kinds it equals the matching doc count.

§Errors
Source

pub fn count_distinct_ids_in_range( &self, index_name: &str, range: impl RangeBounds<Vec<u8>>, ) -> Result<u64>

Count distinct document Ids whose entries fall inside range on the named index’s B-tree, WITHOUT decoding any document. For Each indexes this is the correct shape of the “how many docs match” question — count_index_range returns the entry count, which overshoots when a single doc contributes multiple entries.

Implementation walks the index B-tree, parses the trailing 8-byte big-endian Id suffix from each non-unique key, and tracks the unique set in a bounded std::collections::HashSet capped at MAX_DISTINCT_IDS. Exceeding the cap surfaces Error::DistinctCountExceeded — the caller should narrow the range.

§Per-kind semantics
  • Standard, Composite: equivalent to count_index_range (one entry per doc by construction; the trailing-id-suffix walk still produces the same total).
  • Unique: keys carry NO id suffix — the entry value is the raw 8-byte Id; the walk reads the value instead.
  • Each: the dedup is meaningful — one doc may contribute N entries under N distinct element keys.
§Errors
Source

pub fn all(&self) -> Result<Vec<(Id, T)>>

Materialise every (Id, T) pair in the collection.

Implementation note: M6 returns an owned Vec rather than a streaming iterator because the B+tree range API borrows the pager, and threading that borrow through the mutex guards in the iterator chain is awkward. M7+ may convert to a streaming shape once the index API is in place.

§Errors

Pager / B-tree / codec errors propagated.

Auto Trait Implementations§

§

impl<'tx, T> Freeze for Collection<'tx, T>

§

impl<'tx, T> RefUnwindSafe for Collection<'tx, T>

§

impl<'tx, T> Send for Collection<'tx, T>

§

impl<'tx, T> Sync for Collection<'tx, T>

§

impl<'tx, T> Unpin for Collection<'tx, T>

§

impl<'tx, T> UnsafeUnpin for Collection<'tx, T>

§

impl<'tx, T> UnwindSafe for Collection<'tx, T>

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, 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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V