use std::collections::HashMap;
use std::sync::Arc;
use petgraph::graph::NodeIndex;
use super::DirGraph;
use crate::datatypes::values::Value;
use crate::graph::schema::{ColumnarRow, InternedKey, NodeData, PropertyStorage};
use crate::graph::storage::undo::ColumnarAppendPreImage;
use crate::graph::storage::GraphWrite;
impl DirGraph {
pub fn insert_node_routed(
&mut self,
id: Value,
title: Value,
node_type: &str,
mut properties: HashMap<String, Value>,
) -> NodeIndex {
self.inject_provenance(node_type, &mut properties);
self.register_property_types(node_type, &properties);
let interned_props: Vec<(InternedKey, Value)> = properties
.iter()
.map(|(k, v)| (self.interner.get_or_intern(k), v.clone()))
.collect();
let mut keys: Vec<InternedKey> = interned_props.iter().map(|(k, _)| *k).collect();
keys.sort_unstable_by_key(|k| k.as_u64());
self.ensure_type_schema_keys(node_type, &keys);
let row_id = self.push_node_row(node_type, &id, &title, &interned_props);
let node_type_key = self.interner.get_or_intern(node_type);
let node_data = NodeData {
id: Value::Null,
title: Value::Null,
node_type: node_type_key,
properties: PropertyStorage::Columnar(ColumnarRow::new(row_id)),
};
let idx = GraphWrite::add_node(&mut self.graph, node_data);
GraphWrite::update_row_id(&mut self.graph, idx, row_id);
idx
}
fn push_node_row(
&mut self,
node_type: &str,
id: &Value,
title: &Value,
interned_props: &[(InternedKey, Value)],
) -> u32 {
let store_was_new = self.column_store(node_type).is_none();
self.ensure_column_store_for_push(node_type);
if self.graph.undo_journal_mut().is_some() {
let type_key = InternedKey::from_str(node_type);
let first_append = self
.graph
.undo_journal_mut()
.is_some_and(|journal| journal.claim_columnar_append(type_key));
let captured = first_append
.then(|| {
self.column_store(node_type)
.map(|store| ColumnarAppendPreImage::capture(store))
})
.flatten();
if let (Some(captured), Some(journal)) = (captured, self.graph.undo_journal_mut()) {
captured.record(journal, type_key, store_was_new);
}
}
let store = Arc::make_mut(
self.column_store_mut(node_type)
.expect("ensure_column_store_for_push installed it"),
);
store.push_id(id);
store.push_title(title);
store.push_row(interned_props)
}
fn register_property_types(&mut self, node_type: &str, properties: &HashMap<String, Value>) {
let known = self.node_type_metadata.get(node_type);
let missing: Vec<(String, String)> = properties
.iter()
.filter(|(_, value)| !matches!(value, Value::Null))
.filter(|(key, _)| known.is_none_or(|props| !props.contains_key(*key)))
.map(|(key, value)| (key.clone(), value.type_name().to_string()))
.collect();
if missing.is_empty() {
return;
}
self.upsert_node_type_metadata(node_type, missing.into_iter().collect());
}
}