use super::decode::decoded_column_value;
use super::segments::load_segment_bytes;
use super::state::{ColumnarEngine, SegmentMeta};
use crate::error::LiteError;
use crate::storage::engine::StorageEngine;
use nodedb_columnar::delete_bitmap::DeleteBitmap;
use nodedb_types::value::Value;
impl<S: StorageEngine> ColumnarEngine<S> {
pub async fn list_rows(&self, collection: &str) -> Result<Vec<Vec<Value>>, LiteError> {
let state_arc = self.lookup(collection)?;
struct Snapshot {
memtable_rows: Vec<Vec<Value>>,
seg_metas: Vec<SegmentMeta>,
col_count: usize,
}
let snap = {
let s = Self::lock_state(&state_arc)?;
let memtable_rows: Vec<Vec<Value>> = s
.mutation
.memtable()
.iter_rows()
.collect::<Result<_, _>>()
.map_err(|e| LiteError::Storage {
detail: format!("read memtable row of '{collection}': {e}"),
})?;
Snapshot {
memtable_rows,
seg_metas: s.segments.clone(),
col_count: s.mutation.schema().columns.len(),
}
};
let mut all_rows: Vec<Vec<Value>> = Vec::new();
all_rows.extend(snap.memtable_rows);
for seg_meta in &snap.seg_metas {
if seg_meta.fully_deleted_at_ms.is_some() {
continue;
}
let seg_bytes =
match load_segment_bytes(&*self.storage, collection, seg_meta.segment_id).await? {
Some(b) => b,
None => continue,
};
let reader = nodedb_columnar::reader::SegmentReader::open(&seg_bytes).map_err(|e| {
LiteError::Storage {
detail: format!("open segment {}: {e}", seg_meta.segment_id),
}
})?;
let row_count = reader.row_count() as usize;
if row_count == 0 {
continue;
}
let mut decoded: Vec<nodedb_columnar::reader::DecodedColumn> =
Vec::with_capacity(snap.col_count);
for col_idx in 0..snap.col_count {
let col = reader
.read_column(col_idx)
.map_err(|e| LiteError::Storage {
detail: format!(
"read column {col_idx} of segment {}: {e}",
seg_meta.segment_id
),
})?;
decoded.push(col);
}
for row_idx in 0..row_count {
let row: Vec<Value> = decoded
.iter()
.map(|col| decoded_column_value(col, row_idx))
.collect();
all_rows.push(row);
}
}
Ok(all_rows)
}
pub async fn read_segments(&self, collection: &str) -> Result<Vec<(u32, Vec<u8>)>, LiteError> {
let state_arc = self.lookup(collection)?;
let seg_metas: Vec<SegmentMeta> = {
let s = Self::lock_state(&state_arc)?;
s.segments.clone()
};
let mut segments = Vec::with_capacity(seg_metas.len());
for seg_meta in &seg_metas {
if seg_meta.fully_deleted_at_ms.is_some() {
continue;
}
if let Some(bytes) =
load_segment_bytes(&*self.storage, collection, seg_meta.segment_id).await?
{
segments.push((seg_meta.segment_id, bytes));
}
}
Ok(segments)
}
pub fn delete_bitmap(&self, collection: &str, segment_id: u32) -> Option<DeleteBitmap> {
let guard = self.collections.read().ok()?;
let state_arc = guard.get(collection)?;
let s = state_arc.lock().ok()?;
s.mutation.delete_bitmap(segment_id as u64).cloned()
}
pub fn row_count(&self, collection: &str) -> usize {
let Ok(guard) = self.collections.read() else {
return 0;
};
let Some(state_arc) = guard.get(collection) else {
return 0;
};
let Ok(s) = state_arc.lock() else {
return 0;
};
let seg_rows: u64 = s
.segments
.iter()
.filter(|m| m.fully_deleted_at_ms.is_none())
.map(|m| m.row_count)
.sum();
seg_rows as usize + s.mutation.memtable().row_count()
}
pub fn is_bitemporal(&self, collection: &str) -> bool {
let Ok(guard) = self.collections.read() else {
return false;
};
let Some(state_arc) = guard.get(collection) else {
return false;
};
let Ok(s) = state_arc.lock() else {
return false;
};
s.bitemporal
}
}