use nodedb_types::columnar::{ColumnDef, ColumnType, ColumnarSchema};
use super::column_data::ColumnData;
pub const DEFAULT_FLUSH_THRESHOLD: usize = 65_536;
pub struct ColumnarMemtable {
pub(super) schema: ColumnarSchema,
pub(super) columns: Vec<ColumnData>,
pub(super) row_count: usize,
pub(super) flush_threshold: usize,
}
impl ColumnarMemtable {
pub fn new(schema: &ColumnarSchema) -> Self {
Self::with_threshold(schema, DEFAULT_FLUSH_THRESHOLD)
}
pub fn with_threshold(schema: &ColumnarSchema, flush_threshold: usize) -> Self {
let columns = schema
.columns
.iter()
.map(|col| ColumnData::new(&col.column_type, col.nullable))
.collect();
Self {
schema: schema.clone(),
columns,
row_count: 0,
flush_threshold,
}
}
pub fn row_count(&self) -> usize {
self.row_count
}
pub fn should_flush(&self) -> bool {
self.row_count >= self.flush_threshold
}
pub fn flush_threshold(&self) -> usize {
self.flush_threshold
}
pub fn is_empty(&self) -> bool {
self.row_count == 0
}
pub fn schema(&self) -> &ColumnarSchema {
&self.schema
}
pub fn columns(&self) -> &[ColumnData] {
&self.columns
}
pub(crate) fn from_raw_columns(
schema: &ColumnarSchema,
columns: Vec<ColumnData>,
row_count: usize,
) -> Self {
Self {
schema: schema.clone(),
columns,
row_count,
flush_threshold: DEFAULT_FLUSH_THRESHOLD,
}
}
pub fn add_column(&mut self, name: String, column_type: ColumnType, nullable: bool) {
if self.schema.columns.iter().any(|c| c.name == name) {
return;
}
let existing_rows = self.row_count;
let mut col = ColumnData::new(&column_type, nullable);
if existing_rows > 0 {
col.backfill_nulls(existing_rows);
}
self.columns.push(col);
let col_def = if nullable {
ColumnDef::nullable(name, column_type)
} else {
ColumnDef::required(name, column_type)
};
self.schema.columns.push(col_def);
}
}