use std::sync::OnceLock;
use selene_core::{DbString, EdgeId, LabelSet, NodeId, PropertyMap};
use crate::core_provider::sections::{EdgeRow, NodeRow};
use crate::graph::SeleneGraph;
use crate::store::RowIndex;
pub(super) fn insert_node_row(
graph: &mut SeleneGraph,
id: NodeId,
row: NodeRow,
row_index: usize,
) -> crate::GraphResult<()> {
while graph.node_store.len() < row_index {
graph.node_store.labels.push(LabelSet::new());
graph.node_store.properties.push(PropertyMap::new());
graph.node_store.row_to_id.push(NodeId::TOMBSTONE);
}
if graph.node_store.len() == row_index {
graph.node_store.labels.push(row.labels);
graph.node_store.properties.push(row.properties);
graph.node_store.row_to_id.push(id);
} else {
graph.node_store.labels.set(row_index, row.labels);
graph.node_store.properties.set(row_index, row.properties);
graph.node_store.row_to_id.set(row_index, id);
}
graph
.node_id_to_row
.insert(id, RowIndex::new(row_index as u32));
set_alive(&mut graph.node_store.alive, row_index, row.alive);
Ok(())
}
pub(super) fn insert_edge_row(
graph: &mut SeleneGraph,
id: EdgeId,
row: EdgeRow,
row_index: usize,
) -> crate::GraphResult<()> {
while graph.edge_store.len() < row_index {
graph.edge_store.label.push(edge_hole_label()?);
graph.edge_store.source.push(NodeId::TOMBSTONE);
graph.edge_store.target.push(NodeId::TOMBSTONE);
graph.edge_store.properties.push(PropertyMap::new());
graph.edge_store.row_to_id.push(EdgeId::TOMBSTONE);
}
if graph.edge_store.len() == row_index {
graph.edge_store.label.push(row.label);
graph.edge_store.source.push(row.source);
graph.edge_store.target.push(row.target);
graph.edge_store.properties.push(row.properties);
graph.edge_store.row_to_id.push(id);
} else {
graph.edge_store.label.set(row_index, row.label);
graph.edge_store.source.set(row_index, row.source);
graph.edge_store.target.set(row_index, row.target);
graph.edge_store.properties.set(row_index, row.properties);
graph.edge_store.row_to_id.set(row_index, id);
}
graph
.edge_id_to_row
.insert(id, RowIndex::new(row_index as u32));
set_alive(&mut graph.edge_store.alive, row_index, row.alive);
Ok(())
}
fn set_alive(bitmap: &mut std::sync::Arc<roaring::RoaringBitmap>, row_index: usize, alive: bool) {
let row = u32::try_from(row_index).expect("row index was validated before liveness update");
let bitmap = std::sync::Arc::make_mut(bitmap);
if alive {
bitmap.insert(row);
} else {
bitmap.remove(row);
}
}
fn edge_hole_label() -> Result<DbString, crate::GraphError> {
static CELL: OnceLock<DbString> = OnceLock::new();
if let Some(label) = CELL.get() {
return Ok(label.clone());
}
let label = selene_core::db_string("__selene_hole").map_err(crate::GraphError::Core)?;
let _ = CELL.set(label.clone());
Ok(label)
}