pub struct NodeGroup {
pub columns: Vec<ColumnChunk>,
pub start_offset: u64,
pub num_nodes: u64,
pub version_info: Option<VersionInfo>,
/* private fields */
}Expand description
A node group stores up to NODE_GROUP_SIZE rows in columnar format.
start_offset is the global row index within the owning table where
this group’s data begins. num_nodes counts how many rows have been
appended so far (≤ NODE_GROUP_SIZE).
version_info tracks MVCC insert/delete visibility for concurrent
writers. It is None for single-writer mode (backward compat).
§Disk Spilling
When spiller is set and the memory threshold is exceeded, the group
automatically spills its contents to temp files during append_row().
After ingestion is complete, call flush_with_spiller() instead of
flush() to merge all spills + final in-memory data into the columns.
Fields§
§columns: Vec<ColumnChunk>One in-memory ColumnChunk per column of the table.
start_offset: u64Global row offset within the owning table.
num_nodes: u64Number of rows currently stored in this group.
version_info: Option<VersionInfo>Optional MVCC version tracker for this group.
Implementations§
Source§impl NodeGroup
impl NodeGroup
Sourcepub fn new(num_columns: usize, start_offset: u64) -> Self
pub fn new(num_columns: usize, start_offset: u64) -> Self
Create a new empty node group for num_columns columns.
All columns start with the default NODE_GROUP_SIZE capacity.
start_offset is the global row index in the owning table where
this group begins.
Sourcepub fn with_capacity(
num_columns: usize,
start_offset: u64,
capacity: usize,
) -> Self
pub fn with_capacity( num_columns: usize, start_offset: u64, capacity: usize, ) -> Self
Create a new node group with a custom chunk capacity per column.
Sourcepub fn with_spiller(self, spiller: Arc<Spiller>) -> Self
pub fn with_spiller(self, spiller: Arc<Spiller>) -> Self
Attach a spiller to this node group for disk-based memory management.
When a spiller is attached, append_row() automatically spills the
current buffer to disk when the memory threshold is exceeded, then
continues appending. Call flush_with_spiller() instead of flush()
to merge all spill files + final in-memory data.
Sourcepub fn set_spiller(&mut self, spiller: Arc<Spiller>)
pub fn set_spiller(&mut self, spiller: Arc<Spiller>)
Set the spiller on an existing node group.
Sourcepub fn enable_version_info(&mut self)
pub fn enable_version_info(&mut self)
Enable MVCC version tracking for this node group. Must be called before any inserts if concurrent writes are expected.
Sourcepub fn append_row(&mut self, row: Vec<Value>) -> Result<(), StorageError>
pub fn append_row(&mut self, row: Vec<Value>) -> Result<(), StorageError>
Append a single row (one value per column) to the group.
Returns an error if the number of values does not match the number of columns, or if the group is already full.
If txn_id is Some(...), the insert is recorded in the version
info for MVCC visibility tracking.
Sourcepub fn append_row_with_txn(
&mut self,
row: Vec<Value>,
txn_id: Option<u64>,
) -> Result<(), StorageError>
pub fn append_row_with_txn( &mut self, row: Vec<Value>, txn_id: Option<u64>, ) -> Result<(), StorageError>
Append a row with an optional transaction ID for MVCC tracking.
If a spiller is attached and the in-memory data exceeds the configured
memory threshold, the current buffer is automatically spilled to disk
before appending the new row. This keeps memory usage bounded during
large batch operations like COPY FROM.
Sourcepub fn spill_and_clear(&mut self) -> Result<(), StorageError>
pub fn spill_and_clear(&mut self) -> Result<(), StorageError>
Spill all column chunks to disk and reset the group to empty.
The spill file is tracked so that flush_with_spiller() can later
merge all spilled data back into the persistent columns.
Version info is reset together with the buffer: the records reference local row offsets that are about to be reused, so carrying them over would mis-label rows appended after the spill at the same offsets.
Sourcepub fn restore_spilled(&mut self) -> Result<(), StorageError>
pub fn restore_spilled(&mut self) -> Result<(), StorageError>
Restore all spilled rows back into the in-memory columns.
Merges every tracked spill file (in creation order) followed by the
rows appended since the last spill, so the group’s columns again hold
the complete row set. Spill files are cleaned up on success. This is
the ingest-time counterpart of flush_with_spiller(): it keeps the
in-memory node group authoritative for scans and the column mirror
after a memory-bounded bulk ingest (P51.44).
Sourcepub fn flush_with_spiller(
&mut self,
columns: &mut [Column],
sort_key_column: Option<usize>,
dedup: bool,
) -> Result<usize>
pub fn flush_with_spiller( &mut self, columns: &mut [Column], sort_key_column: Option<usize>, dedup: bool, ) -> Result<usize>
Flush all data to persistent columns, merging any spilled data.
This is the spill-aware alternative to flush(). It merges all
previously spilled files + the current in-memory buffer into the
target columns using a streaming merge. If no spilling occurred,
this falls back to the regular flush().
The optional sort_key_column is the column index to use for
merge ordering and PK deduplication. Pass None for unordered
append (no dedup).
Sourcepub fn num_columns(&self) -> usize
pub fn num_columns(&self) -> usize
Number of columns in this group.
Sourcepub fn has_spill_files(&self) -> bool
pub fn has_spill_files(&self) -> bool
Whether any spill files are still pending merge-back into memory.
Sourcepub fn remaining(&self) -> usize
pub fn remaining(&self) -> usize
Remaining capacity (number of additional rows that can be appended).
Sourcepub fn flush(&mut self, columns: &mut [Column]) -> Result<usize>
pub fn flush(&mut self, columns: &mut [Column]) -> Result<usize>
Flush all buffered data to persistent Column instances.
Each ColumnChunk is flushed to the corresponding Column in the
slice via flush_to_column(). After flushing, the chunks are
cleared and ready for reuse.
Returns the total number of rows flushed.
§Panics
Panics if columns.len() != self.columns.len().
Sourcepub fn flush_copy(&self, columns: &mut [Column]) -> Result<usize>
pub fn flush_copy(&self, columns: &mut [Column]) -> Result<usize>
Flush data to columns but keep the in-memory buffer intact.
Sourcepub fn scan(&self) -> Vec<Vec<Value>>
pub fn scan(&self) -> Vec<Vec<Value>>
Scan all rows currently buffered in the group.
Returns a Vec<Vec<Value>> where result[row][col] is the value
at the given row and column.
Sourcepub fn scan_range(&self, start: usize, count: usize) -> Vec<Vec<Value>>
pub fn scan_range(&self, start: usize, count: usize) -> Vec<Vec<Value>>
Scan a range of buffered rows [start, start + count).
Returns Vec<Vec<Value>> in row-major order.
Sourcepub fn get_value(&self, local_row: usize, col_idx: usize) -> Option<&Value>
pub fn get_value(&self, local_row: usize, col_idx: usize) -> Option<&Value>
Access a single value at the given local row and column index.
Sourcepub fn get_value_with_snapshot(
&self,
local_row: usize,
col_idx: usize,
snapshot_ts: Option<u64>,
commit_history: &HashMap<u64, u64>,
) -> Option<&Value>
pub fn get_value_with_snapshot( &self, local_row: usize, col_idx: usize, snapshot_ts: Option<u64>, commit_history: &HashMap<u64, u64>, ) -> Option<&Value>
Access a single value with MVCC snapshot isolation.
Checks VersionInfo for insert/delete visibility first. If the row
is not visible at snapshot_ts, returns None. Then checks
UpdateInfo version chain on the column chunk for versioned updates.
Sourcepub fn get_value_owned_with_snapshot(
&self,
local_row: usize,
col_idx: usize,
snapshot_ts: Option<u64>,
commit_history: &HashMap<u64, u64>,
) -> Option<Value>
pub fn get_value_owned_with_snapshot( &self, local_row: usize, col_idx: usize, snapshot_ts: Option<u64>, commit_history: &HashMap<u64, u64>, ) -> Option<Value>
Access a single value with MVCC snapshot isolation (owned variant).
Like get_value_with_snapshot but returns Option<Value> instead of
Option<&Value>, enabling proper version chain traversal with
deserialized old values from UpdateInfo.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for NodeGroup
impl RefUnwindSafe for NodeGroup
impl Send for NodeGroup
impl Sync for NodeGroup
impl Unpin for NodeGroup
impl UnsafeUnpin for NodeGroup
impl UnwindSafe for NodeGroup
Blanket Implementations§
impl<T> Allocation for T
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
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