Skip to main content

MutationEngine

Struct MutationEngine 

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

Coordinates all columnar mutations for a single collection.

Owns the memtable, PK index, and per-segment delete bitmaps. Produces WAL records for each mutation that the caller must persist.

Implementations§

Source§

impl MutationEngine

Source

pub fn new(collection: String, schema: ColumnarSchema) -> Self

Create a new mutation engine for a collection.

Source

pub fn memtable(&self) -> &ColumnarMemtable

Access the memtable.

Source

pub fn memtable_mut(&mut self) -> &mut ColumnarMemtable

Mutable access to the memtable (for drain on flush).

Source

pub fn pk_index(&self) -> &PkIndex

Access the PK index.

Source

pub fn pk_index_mut(&mut self) -> &mut PkIndex

Mutable access to the PK index (for cold-start rebuild).

Source

pub fn delete_bitmap(&self, segment_id: u64) -> Option<&DeleteBitmap>

Access a segment’s delete bitmap.

Source

pub fn delete_bitmap_mut(&mut self, segment_id: u64) -> &mut DeleteBitmap

Mutable access to a segment’s delete bitmap. Creates an empty one on first access so callers can mark_deleted_batch unconditionally. Used by temporal-purge paths that tombstone superseded row positions without going through the single-row insert / delete paths.

Source

pub fn memtable_segment_id(&self) -> u64

The virtual segment id used for rows still in the memtable.

Source

pub fn pk_col_indices(&self) -> &[usize]

The schema’s primary-key column indices, in schema order.

Source

pub fn delete_bitmaps(&self) -> &HashMap<u64, DeleteBitmap>

Access all delete bitmaps.

Source

pub fn collection(&self) -> &str

The collection name.

Source

pub fn schema(&self) -> &ColumnarSchema

The schema.

Source

pub fn should_flush(&self) -> bool

Whether the memtable should be flushed.

Source

pub fn memtable_surrogates(&self) -> &[Option<Surrogate>]

Access the per-row surrogate table for the memtable.

Index matches memtable row order; None entries indicate rows inserted without a surrogate (test fixtures, legacy paths).

Source

pub fn scan_memtable_rows(&self) -> impl Iterator<Item = Vec<Value>> + '_

Iterate non-deleted rows in the memtable as Vec<Value>.

Skips rows marked as deleted in the memtable’s virtual segment delete bitmap. For rows in flushed segments, use SegmentReader.

Source

pub fn scan_memtable_rows_with_surrogates( &self, ) -> impl Iterator<Item = (Option<Surrogate>, Vec<Value>)> + '_

Iterate non-deleted rows paired with their surrogate identity.

Yields (Option<Surrogate>, Vec<Value>). The surrogate is None for rows inserted without one (test fixtures, legacy paths). Deleted rows are filtered out exactly as in Self::scan_memtable_rows.

Source

pub fn get_memtable_row(&self, row_idx: usize) -> Option<Vec<Value>>

Get a single row from the memtable by index (None if deleted).

Source

pub fn rollback_memtable_inserts( &mut self, row_count_before: usize, inserted_pks: &[Vec<u8>], displaced: &[(Vec<u8>, RowLocation)], )

Roll back in-memory inserts to row_count_before.

Undoes the effect of one or more inserts that appended rows starting at row_count_before. For each inserted row:

  • The corresponding PK entry is removed from the PK index.
  • If the insert displaced a prior row (upsert tombstone), that prior row’s PK index entry is restored and its tombstone bit cleared.

The memtable is then truncated to row_count_before. Used exclusively by the transaction undo log; never called on the normal write path.

Source

pub fn next_segment_id(&self) -> u64

The segment ID that will be assigned to the next flushed segment.

Use this to obtain the ID to pass to on_memtable_flushed.

Source

pub fn should_compact(&self, segment_id: u64, total_rows: u64) -> bool

Whether a segment should be compacted based on its delete ratio.

Source

pub fn encode_pk_from_row( &self, values: &[Value], ) -> Result<Vec<u8>, ColumnarError>

Encode a PK value as index bytes. Exposed for callers that need to probe the PK index (e.g. ON CONFLICT DO UPDATE routing).

Source§

impl MutationEngine

Source

pub fn on_memtable_flushed( &mut self, new_segment_id: u64, ) -> Result<MutationResult, ColumnarError>

Notify the engine that the memtable was flushed to a new segment.

Updates the PK index to remap memtable entries to the new segment. Returns the WAL record for the flush event, or SegmentIdExhausted if the u64 segment ID counter has wrapped past its maximum.

Source

pub fn on_compaction_complete( &mut self, old_segment_ids: &[u64], new_segment_id: u64, row_mapping: &HashMap<(u64, u32), u32>, ) -> MutationResult

Notify the engine that compaction completed.

Remaps PK index entries and removes old delete bitmaps.

Source§

impl MutationEngine

Source

pub fn insert( &mut self, values: &[Value], ) -> Result<MutationResult, ColumnarError>

Insert a row with upsert-on-duplicate semantics. Returns WAL records to persist.

Validates schema. If the PK already exists, the prior row is tombstoned via the segment’s delete bitmap (a single positional delete) before the new row is appended to the memtable. The PK index is rebound to the new row location. This matches the ClickHouse / Iceberg “sparse PK + positional delete” model and keeps SELECT WHERE pk = X linearizable on one row without a read-time merge pass.

Callers that want strict INSERT (error on duplicate) should check pk_index().contains() themselves before calling; callers that want ON CONFLICT DO NOTHING semantics should use Self::insert_if_absent.

Source

pub fn insert_with_surrogate( &mut self, values: &[Value], surrogate: Surrogate, ) -> Result<MutationResult, ColumnarError>

Insert with a stable cross-engine surrogate identity.

Identical to Self::insert but also records surrogate in the per-row side-table so scan prefilters can perform bitmap membership checks without a separate lookup pass.

Source

pub fn insert_if_absent( &mut self, values: &[Value], ) -> Result<MutationResult, ColumnarError>

INSERT ... ON CONFLICT DO NOTHING semantics: append only if the PK is absent; silently skip on duplicate.

Returns Ok(MutationResult { wal_records }) with an empty vector when the row was skipped, so callers that batch WAL appends can detect no-ops by checking wal_records.is_empty().

Source

pub fn lookup_memtable_row_by_pk(&self, pk_bytes: &[u8]) -> Option<Vec<Value>>

Look up the current row for a PK in the memtable, if present.

Returns None if the PK is not in the index, or if the PK points to a flushed segment (callers needing cross-segment lookup must go through a segment reader separately). This is the fast path used by ON CONFLICT DO UPDATE to read the would-be-merged row when the duplicate hits the memtable — the common case under back-to-back inserts.

Source

pub fn delete( &mut self, pk_value: &Value, ) -> Result<MutationResult, ColumnarError>

Delete a row by PK value. Returns WAL record to persist.

Looks up PK in the index to find the segment + row, then marks the row in the segment’s delete bitmap.

Source

pub fn update( &mut self, old_pk: &Value, new_values: &[Value], ) -> Result<MutationResult, ColumnarError>

Update a row by PK: DELETE old + INSERT new.

updates maps column names to new values. Columns not in the map retain their existing values from the old row.

Returns WAL records for both the delete and the insert.

NOTE: The caller must provide the full old row values for the re-insert. This method takes the complete new row (already merged with old values).

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> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
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

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more