diff --git a/cozo-rocks/src/lib.rs b/cozo-rocks/src/lib.rs index 1f14018e..dbc106fe 100644 --- a/cozo-rocks/src/lib.rs +++ b/cozo-rocks/src/lib.rs @@ -324,7 +324,7 @@ pub trait DBImpl { fn iterator(&self, cf: &ColumnFamilyHandle, options: Option<&ReadOptions>) -> DBIterator; fn create_column_family(&self, name: impl AsRef) -> Result<()>; fn drop_column_family(&self, name: impl AsRef) -> Result<()>; - fn get_column_family_names(&self) -> Vec; + fn all_cf_names(&self) -> Vec; fn get(&self, key: impl AsRef<[u8]>, cf: &ColumnFamilyHandle, options: Option<&ReadOptions>) -> Result>; fn put(&self, key: impl AsRef<[u8]>, val: impl AsRef<[u8]>, cf: &ColumnFamilyHandle, options: Option<&WriteOptions>) @@ -398,7 +398,7 @@ impl DBImpl for DB { } } - fn get_column_family_names(&self) -> Vec { + fn all_cf_names(&self) -> Vec { self.inner.get_column_family_names_raw().iter().map(|v| v.to_string_lossy().to_string()).collect() } diff --git a/src/definition.rs b/src/definition.rs index 527011d0..c18f2196 100644 --- a/src/definition.rs +++ b/src/definition.rs @@ -46,7 +46,7 @@ fn parse_col_name(pair: Pair) -> Result<(String, bool)> { impl StructuredEnvItem { - pub fn build_edge_def(&mut self, pair: Pair, global: bool) -> Result { + pub fn build_edge_def(&mut self, pair: Pair, local_id: usize) -> Result { let mut inner = pair.into_inner(); let src_name = build_name_in_def(inner.next().unwrap(), true)?; let src = self.resolve(&src_name).ok_or(UndefinedType)?; @@ -63,7 +63,7 @@ impl StructuredEnvItem { } else { return Err(WrongType); }; - if global && (!src_id.global || !dst_id.global) { + if local_id == 0 && (!src_id.is_global() || !dst_id.is_global()) { return Err(IncompatibleEdge); } let (keys, cols) = if let Some(p) = inner.next() { @@ -71,7 +71,7 @@ impl StructuredEnvItem { } else { (vec![], vec![]) }; - let table_id = TableId { name: name.clone(), global }; + let table_id = TableId { name: name.clone(), local_id }; let edge = Edge { status: Planned, src: src_id, @@ -97,11 +97,11 @@ impl StructuredEnvItem { Err(NameConflict) } } - pub fn build_node_def(&mut self, pair: Pair, global: bool) -> Result { + pub fn build_node_def(&mut self, pair: Pair, local_id: usize) -> Result { let mut inner = pair.into_inner(); let name = build_name_in_def(inner.next().unwrap(), true)?; let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; - let table_id = TableId { name: name.clone(), global }; + let table_id = TableId { name: name.clone(), local_id }; let node = Node { status: Planned, id: table_id, @@ -125,7 +125,7 @@ impl StructuredEnvItem { } Ok(ret) } - fn build_columns_def(&mut self, pair: Pair, global: bool) -> Result { + fn build_columns_def(&mut self, pair: Pair, local_id: usize) -> Result { let mut inner = pair.into_inner(); let name = build_name_in_def(inner.next().unwrap(), true)?; let node_name = build_name_in_def(inner.next().unwrap(), true)?; @@ -141,8 +141,8 @@ impl StructuredEnvItem { if !keys.is_empty() { return Err(UnexpectedIndexColumns); } - let table_id = TableId { name: name.clone(), global }; - if table_id.global && !node_id.global { + let table_id = TableId { name: name.clone(), local_id }; + if table_id.is_global() && !node_id.is_global() { return Err(IncompatibleEdge); } @@ -158,7 +158,7 @@ impl StructuredEnvItem { } } - fn build_index_def(&mut self, pair: Pair, global: bool) -> Result { + fn build_index_def(&mut self, pair: Pair, local_id: usize) -> Result { let mut inner = pair.into_inner(); let mut name = build_name_in_def(inner.next().unwrap(), true)?; let node_name; @@ -188,9 +188,9 @@ impl StructuredEnvItem { } else { return Err(WrongType); }; - let table_id = TableId { name: name.clone(), global }; + let table_id = TableId { name: name.clone(), local_id }; - if table_id.global && !node_id.global { + if table_id.is_global() && !node_id.is_global() { return Err(IncompatibleEdge); } @@ -303,10 +303,10 @@ impl RocksStorage { let v = it.value(); let mut key_parser = ByteArrayParser::new(&k); let mut data_parser = ByteArrayParser::new(&v); - + key_parser.parse_varint().unwrap(); let table_name = key_parser.parse_value().unwrap().get_string().unwrap(); let table_kind = data_parser.parse_value().unwrap(); - let table_id = TableId { name: table_name, global: true }; + let table_id = TableId { name: table_name, local_id: 0 }; match table_kind { Value::UInt(i) if i == TableKind::Node as u64 => { @@ -350,8 +350,8 @@ impl RocksStorage { Value::UInt(i) if i == TableKind::Edge as u64 => { let src_name = data_parser.parse_value().unwrap().get_string().unwrap(); let dst_name = data_parser.parse_value().unwrap().get_string().unwrap(); - let src_id = TableId { name: src_name, global: true }; - let dst_id = TableId { name: dst_name, global: true }; + let src_id = TableId { name: src_name, local_id: 0 }; + let dst_id = TableId { name: dst_name, local_id: 0 }; let keys: Vec<_> = data_parser.parse_value().unwrap().get_list().unwrap() .into_iter().map(|v| { let mut vs = v.get_list().unwrap().into_iter(); @@ -404,6 +404,7 @@ impl RocksStorage { fn persist_node(&mut self, node: &mut Node) -> Result<()> { let mut key_writer = ByteArrayBuilder::with_capacity(8); + key_writer.build_varint(0); key_writer.build_value(&Value::RefString(&node.id.name)); let mut val_writer = ByteArrayBuilder::with_capacity(128); val_writer.build_value(&Value::UInt(TableKind::Node as u64)); @@ -429,6 +430,7 @@ impl RocksStorage { fn persist_edge(&mut self, edge: &mut Edge) -> Result<()> { let mut key_writer = ByteArrayBuilder::with_capacity(8); + key_writer.build_varint(0); key_writer.build_value(&Value::RefString(&edge.id.name)); let mut val_writer = ByteArrayBuilder::with_capacity(128); @@ -500,6 +502,7 @@ impl Evaluator { r @ (Rule::global_def | Rule::local_def) => { let inner = pair.into_inner().next().unwrap(); let global = r == Rule::global_def; + let local_id = self.get_next_local_id(global); let env_to_build = if global { self.s_envs.root_mut() } else { @@ -507,16 +510,16 @@ impl Evaluator { }; new_tables.push((global, match inner.as_rule() { Rule::node_def => { - env_to_build.build_node_def(inner, global)? + env_to_build.build_node_def(inner, local_id)? } Rule::edge_def => { - env_to_build.build_edge_def(inner, global)? + env_to_build.build_edge_def(inner, local_id)? } Rule::columns_def => { - env_to_build.build_columns_def(inner, global)? + env_to_build.build_columns_def(inner, local_id)? } Rule::index_def => { - env_to_build.build_index_def(inner, global)? + env_to_build.build_index_def(inner, local_id)? } _ => todo!() })); diff --git a/src/eval.rs b/src/eval.rs index 78c0a14e..ae166940 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; use crate::ast::Expr; use crate::ast::Expr::*; use crate::error::Result; @@ -11,6 +13,17 @@ use crate::storage::{DummyStorage, RocksStorage, Storage}; pub struct Evaluator { pub s_envs: StructuredEnv, pub storage: S, + pub last_local_id: Arc, +} + +impl Evaluator { + pub fn get_next_local_id(&self, is_global: bool) -> usize { + if is_global { + 0 + } else { + self.last_local_id.fetch_add(1, Ordering::Relaxed) + } + } } pub type EvaluatorWithStorage = Evaluator; @@ -18,13 +31,21 @@ pub type BareEvaluator = Evaluator; impl EvaluatorWithStorage { pub fn new(path: String) -> Result { - Ok(Self { s_envs: StructuredEnv::new(), storage: RocksStorage::new(path)? }) + Ok(Self { + s_envs: StructuredEnv::new(), + storage: RocksStorage::new(path)?, + last_local_id: Arc::new(AtomicUsize::new(1)), + }) } } impl Default for BareEvaluator { fn default() -> Self { - Self { s_envs: StructuredEnv::new(), storage: DummyStorage } + Self { + s_envs: StructuredEnv::new(), + storage: DummyStorage, + last_local_id: Arc::new(AtomicUsize::new(0)), + } } } diff --git a/src/storage.rs b/src/storage.rs index f54b3a51..c201ff79 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -86,7 +86,7 @@ mod tests { builder.build_value(&Value::RefString("Another key")); let key2 = builder; let cf = db.get_cf_handle("default").unwrap(); - println!("{:?}", db.get_column_family_names()); + println!("{:?}", db.all_cf_names()); let val = db.get(&key, &cf, None).unwrap(); println!("before anything {}", val.is_none()); diff --git a/src/typing.rs b/src/typing.rs index e8ab2b68..dcbc90f6 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -55,16 +55,24 @@ pub enum StorageStatus { } #[derive(PartialEq, Eq, Ord, PartialOrd, Clone)] -pub struct TableId{ +pub struct TableId { pub name: String, - pub global: bool + pub local_id: usize, +} + +impl TableId { + pub fn is_global(&self) -> bool { + self.local_id == 0 + } } impl Debug for TableId { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str( if self.global { "+" } else {"-"})?; f.write_str(&self.name)?; + if self.local_id > 0 { + f.write_str(&format!("({})", self.local_id))?; + } Ok(()) } } diff --git a/src/value.rs b/src/value.rs index d566ed1b..26c43992 100644 --- a/src/value.rs +++ b/src/value.rs @@ -343,7 +343,7 @@ pub struct ByteArrayBuilder> { byte_writer: T, } -impl > AsRef<[u8]> for ByteArrayBuilder { +impl> AsRef<[u8]> for ByteArrayBuilder { fn as_ref(&self) -> &[u8] { self.byte_writer.as_ref() } @@ -421,7 +421,7 @@ impl> ByteArrayBuilder { self } - pub fn build_value(&mut self, v: &Value) -> &mut Self{ + pub fn build_value(&mut self, v: &Value) -> &mut Self { use ValueTag::*; match v { @@ -477,8 +477,14 @@ impl> ByteArrayBuilder { pub fn cozo_comparator_v1(a: &[u8], b: &[u8]) -> i8 { - match cmp_data(&mut ByteArrayParser { bytes: a, current: 0 }, - &mut ByteArrayParser { bytes: b, current: 0 }) { + let mut ba = &mut ByteArrayParser { bytes: a, current: 0 }; + let mut bb = &mut ByteArrayParser { bytes: b, current: 0 }; + match ba.compare_varint(&mut bb) { + Less => return -1, + Greater => return 1, + Equal => {} + } + match cmp_data(&mut ba, &mut bb) { Less => -1, Equal => 0, Greater => 1