From bf8c6db090558cd51f955edcb776296a688d6ed4 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Mon, 11 Apr 2022 18:39:18 +0800 Subject: [PATCH] start storage --- .gitignore | 1 + src/definition.rs | 128 +++++++++++++++-------- src/env.rs | 170 ++++++++++++++++++++++++++++++- src/error.rs | 3 + src/eval.rs | 26 ++--- src/lib.rs | 3 +- src/parser.rs | 36 +++---- src/storage.rs | 42 ++++++++ src/typing.rs | 253 ++++++++++++++-------------------------------- src/value.rs | 15 +++ 10 files changed, 419 insertions(+), 258 deletions(-) create mode 100644 src/storage.rs diff --git a/.gitignore b/.gitignore index 07cf1c95..1c3e7955 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk +_path* \ No newline at end of file diff --git a/src/definition.rs b/src/definition.rs index e937604d..720d5d50 100644 --- a/src/definition.rs +++ b/src/definition.rs @@ -1,13 +1,15 @@ use pest::iterators::{Pair, Pairs}; use crate::ast::parse_string; -use crate::env::Env; +use crate::env::{Env, StructuredEnvItem}; use crate::error::Result; use crate::error::CozoError::*; +use crate::eval::Evaluator; use crate::parser::{Rule}; -use crate::typing::{Col, Columns, Edge, Index, Node, Structured, StructuredEnv, StructuredEnvItem, TableId, Typing}; +use crate::storage::Storage; +use crate::typing::{Col, Columns, Edge, Index, Node, Structured, TableId, Typing}; use crate::typing::Persistence::{Global, Local}; -use crate::typing::StorageStatus::Planned; -use crate::value::Value; +use crate::typing::StorageStatus::{Planned, Stored}; +use crate::value::{ByteArrayBuilder, Value}; fn parse_ident(pair: Pair) -> String { pair.as_str().to_string() @@ -41,11 +43,11 @@ fn parse_col_name(pair: Pair) -> Result<(String, bool)> { impl StructuredEnvItem { - pub fn build_edge_def(&mut self, pair: Pair, table_id: TableId) -> Result<()> { + pub fn build_edge_def(&mut self, pair: Pair, table_id: TableId) -> 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)?; - let src_id = if let Structured::Node(n, _) = src { + let src_id = if let Structured::Node(n) = src { n.id } else { return Err(WrongType); @@ -53,7 +55,7 @@ impl StructuredEnvItem { let name = build_name_in_def(inner.next().unwrap(), true)?; let dst_name = build_name_in_def(inner.next().unwrap(), true)?; let dst = self.resolve(&dst_name).ok_or(UndefinedType)?; - let dst_id = if let Structured::Node(n, _) = dst { + let dst_id = if let Structured::Node(n) = dst { n.id } else { return Err(WrongType); @@ -67,34 +69,36 @@ impl StructuredEnvItem { (vec![], vec![]) }; let edge = Edge { + status: Planned, src: src_id, dst: dst_id, id: table_id, keys, cols, }; - if self.define_new(name.to_string(), Structured::Edge(edge, Planned)) { - if let Some(Structured::Node(src, _)) = self.resolve_mut(&src_name) { + if self.define_new(name.to_string(), Structured::Edge(edge)) { + if let Some(Structured::Node(src)) = self.resolve_mut(&src_name) { src.out_e.push(table_id); } else { unreachable!() } - if let Some(Structured::Node(dst, _)) = self.resolve_mut(&dst_name) { + if let Some(Structured::Node(dst)) = self.resolve_mut(&dst_name) { dst.in_e.push(table_id); } else { unreachable!() } - Ok(()) + Ok(name.to_string()) } else { Err(NameConflict) } } - pub fn build_node_def(&mut self, pair: Pair, table_id: TableId) -> Result<()> { + pub fn build_node_def(&mut self, pair: Pair, table_id: TableId) -> 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 node = Node { + status: Planned, id: table_id, keys, cols, @@ -102,8 +106,8 @@ impl StructuredEnvItem { in_e: vec![], attached: vec![], }; - if self.define_new(name.to_string(), Structured::Node(node, Planned)) { - Ok(()) + if self.define_new(name.to_string(), Structured::Node(node)) { + Ok(name.to_string()) } else { Err(NameConflict) } @@ -116,38 +120,39 @@ impl StructuredEnvItem { } Ok(ret) } - fn build_columns_def(&mut self, pair: Pair, table_id: TableId) -> Result<()> { + fn build_columns_def(&mut self, pair: Pair, table_id: TableId) -> 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)?; let node = self.resolve(&node_name).ok_or(UndefinedType)?; - let node_id = if let Structured::Node(n, _) = node { + let node_id = if let Structured::Node(n) = node { n.id - } else if let Structured::Edge(n, _) = node { + } else if let Structured::Edge(n) = node { n.id } else { return Err(WrongType); }; let (keys, cols) = self.build_col_defs(inner.next().unwrap())?; if !keys.is_empty() { - return Err(UnexpectedIndexColumns) + return Err(UnexpectedIndexColumns); } if table_id.0 == Global && node_id.0 == Local { return Err(IncompatibleEdge); } - if self.define_new(name, Structured::Columns(Columns { + if self.define_new(name.clone(), Structured::Columns(Columns { + status: Planned, id: table_id, attached: node_id, - cols - }, Planned)) { - Ok(()) + cols, + })) { + Ok(name) } else { Err(NameConflict) } } - fn build_index_def(&mut self, pair: Pair, table_id: TableId) -> Result<()> { + fn build_index_def(&mut self, pair: Pair, table_id: TableId) -> Result { let mut inner = pair.into_inner(); let mut name = build_name_in_def(inner.next().unwrap(), true)?; let node_name; @@ -172,7 +177,7 @@ impl StructuredEnvItem { }; let node = self.resolve(&node_name).ok_or(UndefinedType)?; - let node_id = if let Structured::Node(n, _) = node { + let node_id = if let Structured::Node(n) = node { n.id } else { return Err(WrongType); @@ -183,12 +188,13 @@ impl StructuredEnvItem { // TODO: make sure cols make sense - if self.define_new(name, Structured::Index(Index { + if self.define_new(name.clone(), Structured::Index(Index { + status: Planned, id: table_id, attached: node_id, cols: col_list, - }, Planned)) { - Ok(()) + })) { + Ok(name) } else { Err(NameConflict) } @@ -238,9 +244,9 @@ impl StructuredEnvItem { let typ = self.build_type(pairs.next().unwrap())?; let default = if let Some(p) = pairs.next() { // TODO: check value is suitable for the type - Some(self.build_default_value(p)?) + self.build_default_value(p)? } else { - None + Value::Null }; Ok((Col { name, @@ -265,41 +271,75 @@ impl StructuredEnvItem { } } -impl StructuredEnv { +impl Storage { + 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::UInt(node.id.1 as u64)); + // println!("{:#?}", node); + // println!("{:?}", key_writer.get()); + node.status = Stored; + Ok(()) + } + + fn persist_edge(&mut self, edge: &mut Edge) -> Result<()> { + edge.status = Stored; + Ok(()) + } +} + +impl Evaluator { + pub fn restore_metadata(&mut self) {} + + fn persist_change(&mut self, tname: &str) -> Result<()> { + let tbl = self.s_envs.resolve_mut(tname).unwrap(); + match tbl { + Structured::Node(n) => self.storage.persist_node(n), + Structured::Edge(e) => self.storage.persist_edge(e), + Structured::Columns(_) => unimplemented!(), + Structured::Index(_) => unimplemented!(), + Structured::Typing(_) => panic!(), + } + } + + pub fn build_table(&mut self, pairs: Pairs) -> Result<()> { + let mut new_tables = vec![]; for pair in pairs { match pair.as_rule() { r @ (Rule::global_def | Rule::local_def) => { let inner = pair.into_inner().next().unwrap(); let is_local = r == Rule::local_def; - let next_id = self.get_next_table_id(is_local); + let next_id = self.s_envs.get_next_table_id(is_local); let env_to_build = if is_local { - self.root_mut() + self.s_envs.root_mut() } else { - self.cur_mut() + self.s_envs.cur_mut() }; - // println!("{:?} {:?}", r, inner.as_rule()); - match inner.as_rule() { + new_tables.push(match inner.as_rule() { Rule::node_def => { - env_to_build.build_node_def(inner, next_id)?; + env_to_build.build_node_def(inner, next_id)? } Rule::edge_def => { - env_to_build.build_edge_def(inner, next_id)?; + env_to_build.build_edge_def(inner, next_id)? } Rule::columns_def => { - env_to_build.build_columns_def(inner, next_id)?; + env_to_build.build_columns_def(inner, next_id)? } Rule::index_def => { - env_to_build.build_index_def(inner, next_id)?; + env_to_build.build_index_def(inner, next_id)? } _ => todo!() - } + }); } Rule::EOI => {} _ => unreachable!() } } + for tname in &new_tables { + self.persist_change(tname).unwrap(); // TODO proper error handling + } Ok(()) } } @@ -326,9 +366,9 @@ mod tests { } "#; let parsed = Parser::parse(Rule::file, s).unwrap(); - let mut env = StructuredEnv::new(); - env.build_table(parsed).unwrap(); - println!("{:#?}", env.resolve("Person")); - println!("{:#?}", env.resolve("Friend")); + let mut eval = Evaluator::new("_path_for_rocksdb_storagex".to_string()).unwrap(); + eval.build_table(parsed).unwrap(); + // println!("{:#?}", eval.s_envs.resolve("Person")); + // println!("{:#?}", eval.s_envs.resolve("Friend")); } } \ No newline at end of file diff --git a/src/env.rs b/src/env.rs index 46bcbf93..ba9d9dec 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,3 +1,6 @@ +use std::collections::BTreeMap; +use crate::typing::{define_base_types, Persistence, Structured, TableId}; + pub trait Env { fn define(&mut self, name: String, value: V) -> Option; fn define_new(&mut self, name: String, value: V) -> bool; @@ -12,4 +15,169 @@ pub trait LayeredEnv : Env { fn root_resolve(&self, name: &str) -> Option<&V>; fn root_resolve_mut(&mut self, name: &str) -> Option<&mut V>; fn root_undef(&mut self, name: &str) -> Option; -} \ No newline at end of file +} + + + +pub struct StructuredEnvItem { + map: BTreeMap, +} + + +pub struct StructuredEnv { + stack: Vec, +} + + +impl StructuredEnv { + pub fn new() -> Self { + let mut root = StructuredEnvItem { map: BTreeMap::new() }; + define_base_types(&mut root); + Self { stack: vec![root] } + } + + pub fn root(&self) -> &StructuredEnvItem { + &self.stack[0] + } + + pub fn root_mut(&mut self) -> &mut StructuredEnvItem { + &mut self.stack[0] + } + + pub fn cur(&self) -> &StructuredEnvItem { + self.stack.last().unwrap() + } + + pub fn cur_mut(&mut self) -> &mut StructuredEnvItem { + self.stack.last_mut().unwrap() + } + + pub fn push(&mut self) { + self.stack.push(StructuredEnvItem { map: BTreeMap::new() }) + } + pub fn pop(&mut self) -> bool { + if self.stack.len() <= 1 { + false + } else { + self.stack.pop(); + true + } + } + + pub fn get_next_table_id(&self, local: bool) -> TableId { + let mut id = 0; + let persistence = if local { Persistence::Local } else { Persistence::Global }; + for env in &self.stack { + for item in env.map.values() { + if let Some(TableId(p, eid)) = item.storage_id() { + if p == persistence { + id = id.max(eid); + } + } + } + } + TableId(persistence, id + 1) + } +} + +impl LayeredEnv for StructuredEnv { + fn root_define(&mut self, name: String, value: Structured) -> Option { + self.root_mut().define(name, value) + } + + fn root_define_new(&mut self, name: String, value: Structured) -> bool { + self.root_mut().define_new(name, value) + } + + fn root_resolve(&self, name: &str) -> Option<&Structured> { + self.root().resolve(name) + } + + fn root_resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { + self.root_mut().resolve_mut(name) + } + + fn root_undef(&mut self, name: &str) -> Option { + self.root_mut().undef(name) + } +} + +impl Env for StructuredEnv { + fn define(&mut self, name: String, value: Structured) -> Option { + self.stack.last_mut().unwrap().define(name, value) + } + + fn define_new(&mut self, name: String, value: Structured) -> bool { + self.stack.last_mut().unwrap().define_new(name, value) + } + + fn resolve(&self, name: &str) -> Option<&Structured> { + let mut res = None; + for item in self.stack.iter().rev() { + res = item.resolve(name); + if res.is_some() { + return res; + } + } + res + } + + fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { + let mut res = None; + for item in self.stack.iter_mut().rev() { + res = item.resolve_mut(name); + if res.is_some() { + return res; + } + } + res + } + + fn undef(&mut self, name: &str) -> Option { + let mut res = None; + for item in self.stack.iter_mut().rev() { + res = item.undef(name); + if res.is_some() { + return res; + } + } + res + } +} + +impl Env for StructuredEnvItem { + fn define(&mut self, name: String, value: Structured) -> Option { + let old = self.map.remove(&name); + self.map.insert(name, value); + old + } + + fn define_new(&mut self, name: String, value: Structured) -> bool { + if let std::collections::btree_map::Entry::Vacant(e) = self.map.entry(name) { + e.insert(value); + true + } else { + false + } + } + + fn resolve(&self, name: &str) -> Option<&Structured> { + self.map.get(name) + } + + fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { + self.map.get_mut(name) + } + + + fn undef(&mut self, name: &str) -> Option { + self.map.remove(name) + } +} + + +impl Default for StructuredEnv { + fn default() -> Self { + StructuredEnv::new() + } +} diff --git a/src/error.rs b/src/error.rs index e518eaad..33a3d371 100644 --- a/src/error.rs +++ b/src/error.rs @@ -39,6 +39,9 @@ pub enum CozoError { #[error(transparent)] Parse(#[from] pest::error::Error), + + #[error(transparent)] + Storage(#[from] rocksdb::Error) } pub type Result = result::Result; \ No newline at end of file diff --git a/src/eval.rs b/src/eval.rs index 64cf4026..63c7c8a0 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -5,23 +5,20 @@ use crate::error::CozoError; use crate::error::CozoError::*; use crate::value::Value::*; use crate::ast::*; -use crate::typing::StructuredEnv; +use crate::env::StructuredEnv; +use crate::storage::Storage; pub struct Evaluator { pub s_envs: StructuredEnv, + pub storage: Storage, } impl Evaluator { - pub fn new() -> Self { - Self { s_envs: StructuredEnv::new() } + pub fn new(path: String) -> Result { + Ok(Self { s_envs: StructuredEnv::new(), storage: Storage::new(path)? }) } } -impl Default for Evaluator { - fn default() -> Self { - Evaluator::new() - } -} impl<'a> ExprVisitor<'a, Result>> for Evaluator { fn visit_expr(&mut self, ex: &Expr<'a>) -> Result> { @@ -135,7 +132,6 @@ impl Evaluator { } } - fn div_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -183,7 +179,6 @@ impl Evaluator { } } - fn eq_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -201,7 +196,6 @@ impl Evaluator { } } - fn ne_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -219,7 +213,6 @@ impl Evaluator { } } - fn gt_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -245,7 +238,6 @@ impl Evaluator { } } - fn ge_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -271,7 +263,6 @@ impl Evaluator { } } - fn lt_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -322,7 +313,6 @@ impl Evaluator { } } - fn pow_exprs<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { match exprs { [a, b] => { @@ -391,7 +381,6 @@ impl Evaluator { }) } - fn minus_expr<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { Ok(match exprs { [a] => { @@ -408,7 +397,6 @@ impl Evaluator { }) } - fn test_null_expr<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { Ok(match exprs { [a] => { @@ -467,7 +455,6 @@ impl Evaluator { } } - fn and_expr<'a>(&mut self, exprs: &[Expr<'a>]) -> Result> { let mut unevaluated = vec![]; let mut no_null = true; @@ -507,7 +494,7 @@ mod tests { #[test] fn operators() { - let mut ev = Evaluator::new(); + let mut ev = Evaluator::new("_path_for_rocksdb_storage".to_string()).unwrap(); println!("{:#?}", ev.visit_expr(&parse_expr_from_str("1/10+(-2+3)*4^5").unwrap()).unwrap()); println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && false").unwrap()).unwrap()); @@ -515,5 +502,6 @@ mod tests { println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true || null").unwrap()).unwrap()); println!("{:#?}", ev.visit_expr(&parse_expr_from_str("null || true").unwrap()).unwrap()); println!("{:#?}", ev.visit_expr(&parse_expr_from_str("true && null").unwrap()).unwrap()); + ev.storage.delete().unwrap(); } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 9707614d..1c2037bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,5 @@ pub mod parser; pub mod eval; pub mod function; pub mod error; -pub mod definition; \ No newline at end of file +pub mod definition; +pub mod storage; \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index a63c7962..720b13b7 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -10,24 +10,24 @@ pub struct Parser; mod tests { use super::*; use pest::Parser as PestParser; - - #[test] - fn db() { - use rocksdb::{DB, Options}; -// NB: db is automatically closed at end of lifetime - let path = "_path_for_rocksdb_storage"; - { - let db = DB::open_default(path).unwrap(); - db.put("真二", "你好👋").unwrap(); - match db.get_pinned("真二") { - Ok(Some(value)) => println!("retrieved value {}", std::str::from_utf8(&value).unwrap()), - Ok(None) => println!("value not found"), - Err(e) => println!("operational problem encountered: {}", e), - } - db.delete(b"my key").unwrap(); - } - let _ = DB::destroy(&Options::default(), path); - } +// +// #[test] +// fn db() { +// use rocksdb::{DB, Options}; +// // NB: db is automatically closed at end of lifetime +// let path = "_path_for_rocksdb_storage"; +// { +// let db = DB::open_default(path).unwrap(); +// db.put("真二", "你好👋").unwrap(); +// match db.get_pinned("真二") { +// Ok(Some(value)) => println!("retrieved value {}", std::str::from_utf8(&value).unwrap()), +// Ok(None) => println!("value not found"), +// Err(e) => println!("operational problem encountered: {}", e), +// } +// db.delete(b"my key").unwrap(); +// } +// let _ = DB::destroy(&Options::default(), path); +// } #[test] fn identifiers() { diff --git a/src/storage.rs b/src/storage.rs new file mode 100644 index 00000000..a4fcc85c --- /dev/null +++ b/src/storage.rs @@ -0,0 +1,42 @@ +use rocksdb::{DB, Options, ColumnFamilyDescriptor}; +use crate::error::Result; +use crate::value::cozo_comparator_v1; + + +pub struct Storage { + db: Option, + options: Options, + path: String, +} + +impl Storage { + pub fn new(path: String) -> Result { + let mut options = Options::default(); + + options.create_missing_column_families(true); + options.create_if_missing(true); + options.set_comparator("cozo_comparator_v1", cozo_comparator_v1); + + let main_cf = ColumnFamilyDescriptor::new("main", options.clone()); + let temp_cf = ColumnFamilyDescriptor::new("temp", options.clone()); + let db = DB::open_cf_descriptors(&options, &path, vec![main_cf, temp_cf])?; + + Ok(Storage { db: Some(db), options, path }) + } + pub fn delete(&mut self) -> Result<()> { + drop(self.db.take()); + DB::destroy(&self.options, &self.path)?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn storage() { + let mut s = Storage::new("_path_for_rocksdb_storage".to_string()).unwrap(); + s.delete().unwrap(); + } +} \ No newline at end of file diff --git a/src/typing.rs b/src/typing.rs index 7308d92b..c70d0746 100644 --- a/src/typing.rs +++ b/src/typing.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; -use crate::env::{Env, LayeredEnv}; +use std::fmt::{Debug, Display, Formatter, Write}; +use crate::env::{Env}; use crate::value::Value; #[derive(Debug, Eq, PartialEq, Clone)] @@ -37,175 +38,12 @@ pub enum BaseType { Crs, } -pub struct StructuredEnvItem { - map: BTreeMap, -} - - -pub struct StructuredEnv { - stack: Vec, -} - - -impl StructuredEnv { - pub fn new() -> Self { - let mut root = StructuredEnvItem { map: BTreeMap::new() }; - define_base_types(&mut root); - Self { stack: vec![root] } - } - - pub fn root(&self) -> &StructuredEnvItem { - &self.stack[0] - } - - pub fn root_mut(&mut self) -> &mut StructuredEnvItem { - &mut self.stack[0] - } - - pub fn cur(&self) -> &StructuredEnvItem { - self.stack.last().unwrap() - } - - pub fn cur_mut(&mut self) -> &mut StructuredEnvItem { - self.stack.last_mut().unwrap() - } - - pub fn push(&mut self) { - self.stack.push(StructuredEnvItem { map: BTreeMap::new() }) - } - pub fn pop(&mut self) -> bool { - if self.stack.len() <= 1 { - false - } else { - self.stack.pop(); - true - } - } - - pub fn get_next_table_id(&self, local: bool) -> TableId { - let mut id = 0; - let persistence = if local { Persistence::Local } else { Persistence::Global }; - for env in &self.stack { - for item in env.map.values() { - if let Some(TableId(p, eid)) = item.storage_id() { - if p == persistence { - id = id.max(eid); - } - } - } - } - TableId(persistence, id + 1) - } -} - -impl LayeredEnv for StructuredEnv { - fn root_define(&mut self, name: String, value: Structured) -> Option { - self.root_mut().define(name, value) - } - - fn root_define_new(&mut self, name: String, value: Structured) -> bool { - self.root_mut().define_new(name, value) - } - - fn root_resolve(&self, name: &str) -> Option<&Structured> { - self.root().resolve(name) - } - - fn root_resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { - self.root_mut().resolve_mut(name) - } - - fn root_undef(&mut self, name: &str) -> Option { - self.root_mut().undef(name) - } -} - -impl Env for StructuredEnv { - fn define(&mut self, name: String, value: Structured) -> Option { - self.stack.last_mut().unwrap().define(name, value) - } - - fn define_new(&mut self, name: String, value: Structured) -> bool { - self.stack.last_mut().unwrap().define_new(name, value) - } - - fn resolve(&self, name: &str) -> Option<&Structured> { - let mut res = None; - for item in self.stack.iter().rev() { - res = item.resolve(name); - if res.is_some() { - return res; - } - } - res - } - - fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { - let mut res = None; - for item in self.stack.iter_mut().rev() { - res = item.resolve_mut(name); - if res.is_some() { - return res; - } - } - res - } - - fn undef(&mut self, name: &str) -> Option { - let mut res = None; - for item in self.stack.iter_mut().rev() { - res = item.undef(name); - if res.is_some() { - return res; - } - } - res - } -} - -impl Env for StructuredEnvItem { - fn define(&mut self, name: String, value: Structured) -> Option { - let old = self.map.remove(&name); - self.map.insert(name, value); - old - } - - fn define_new(&mut self, name: String, value: Structured) -> bool { - if let std::collections::btree_map::Entry::Vacant(e) = self.map.entry(name) { - e.insert(value); - true - } else { - false - } - } - - fn resolve(&self, name: &str) -> Option<&Structured> { - self.map.get(name) - } - - fn resolve_mut(&mut self, name: &str) -> Option<&mut Structured> { - self.map.get_mut(name) - } - - - fn undef(&mut self, name: &str) -> Option { - self.map.remove(name) - } -} - - -impl Default for StructuredEnv { - fn default() -> Self { - StructuredEnv::new() - } -} - #[derive(Debug, PartialEq, Clone)] pub struct Col { pub name: String, pub typ: Typing, - pub default: Option>, + pub default: Value<'static>, } #[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone, Copy)] @@ -229,6 +67,7 @@ pub struct ColumnId(TableId, usize); #[derive(Debug, PartialEq, Clone)] pub struct Node { + pub status: StorageStatus, pub id: TableId, pub keys: Vec, pub cols: Vec, @@ -239,6 +78,7 @@ pub struct Node { #[derive(Debug, PartialEq, Clone)] pub struct Edge { + pub status: StorageStatus, pub src: TableId, pub dst: TableId, pub id: TableId, @@ -248,6 +88,7 @@ pub struct Edge { #[derive(Debug, PartialEq, Clone)] pub struct Columns { + pub status: StorageStatus, pub attached: TableId, pub id: TableId, pub cols: Vec, @@ -255,13 +96,14 @@ pub struct Columns { #[derive(Debug, PartialEq, Clone)] pub struct Index { + pub status: StorageStatus, pub id: TableId, pub attached: TableId, pub cols: Vec, } -#[derive(Debug, Eq, PartialEq, Clone)] +#[derive(Eq, PartialEq, Clone)] pub enum Typing { Any, Base(BaseType), @@ -271,23 +113,84 @@ pub enum Typing { NamedTuple(BTreeMap), } +impl Display for Typing { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Typing::Any => f.write_str("Any")?, + Typing::Base(b) => { + match b { + BaseType::Bool => f.write_str("Bool")?, + BaseType::Int => f.write_str("Int")?, + BaseType::UInt => f.write_str("UInt")?, + BaseType::Float => f.write_str("Float")?, + BaseType::String => f.write_str("String")?, + BaseType::BitArr => f.write_str("BitArr")?, + BaseType::U8Arr => f.write_str("U8Arr")?, + BaseType::I8Arr => f.write_str("I8Arr")?, + BaseType::I16Arr => f.write_str("I16Arr")?, + BaseType::U16Arr => f.write_str("U16Arr")?, + BaseType::I32Arr => f.write_str("I32Arr")?, + BaseType::U32Arr => f.write_str("U32Arr")?, + BaseType::I64Arr => f.write_str("I64Arr")?, + BaseType::U64Arr => f.write_str("U64Arr")?, + BaseType::F16Arr => f.write_str("F16Arr")?, + BaseType::F32Arr => f.write_str("F32Arr")?, + BaseType::F64Arr => f.write_str("F64Arr")?, + BaseType::C32Arr => f.write_str("C32Arr")?, + BaseType::C64Arr => f.write_str("C64Arr")?, + BaseType::C128Arr => f.write_str("C128Arr")?, + BaseType::Uuid => f.write_str("Uuid")?, + BaseType::Timestamp => f.write_str("Timestamp")?, + BaseType::Datetime => f.write_str("Datetime")?, + BaseType::Timezone => f.write_str("Timezone")?, + BaseType::Date => f.write_str("Date")?, + BaseType::Time => f.write_str("Time")?, + BaseType::Duration => f.write_str("Duration")?, + BaseType::BigInt => f.write_str("BigInt")?, + BaseType::BigDecimal => f.write_str("BigDecimal")?, + BaseType::Inet => f.write_str("Inet")?, + BaseType::Crs => f.write_str("Crs")? + } + } + Typing::HList(l) => { + f.write_char('[')?; + Display::fmt(l, f)?; + f.write_char(']')?; + } + Typing::Nullable(d) => { + f.write_char('?')?; + Display::fmt(d, f)?; + } + Typing::Tuple(_) => todo!(), + Typing::NamedTuple(_) => todo!() + } + Ok(()) + } +} + +impl Debug for Typing { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + Display::fmt(self, f) + } +} + #[derive(Debug, PartialEq, Clone)] pub enum Structured { Typing(Typing), - Node(Node, StorageStatus), - Edge(Edge, StorageStatus), - Columns(Columns, StorageStatus), - Index(Index, StorageStatus), + Node(Node), + Edge(Edge), + Columns(Columns), + Index(Index), } impl Structured { - fn storage_id(&self) -> Option { + pub fn storage_id(&self) -> Option { match self { Structured::Typing(_) => None, - Structured::Node(n, _) => Some(n.id), - Structured::Edge(e, _) => Some(e.id), - Structured::Columns(c, _) => Some(c.id), - Structured::Index(i, _) => Some(i.id) + Structured::Node(n) => Some(n.id), + Structured::Edge(e) => Some(e.id), + Structured::Columns(c) => Some(c.id), + Structured::Index(i) => Some(i.id) } } } diff --git a/src/value.rs b/src/value.rs index c543771c..f0fa9cbe 100644 --- a/src/value.rs +++ b/src/value.rs @@ -327,7 +327,17 @@ pub struct ByteArrayBuilder { byte_writer: T, } +impl ByteArrayBuilder> { + pub fn with_capacity(size: usize) -> Self { + Self::new(Vec::with_capacity(size)) + } +} + impl ByteArrayBuilder { + pub fn get(self) -> T { + self.byte_writer + } + pub fn new(byte_writer: T) -> Self { Self { byte_writer } } @@ -448,6 +458,11 @@ pub fn cmp_keys<'a>(pa: &mut ByteArrayParser<'a>, pb: &mut ByteArrayParser<'a>) cmp_data(pa, pb) } +pub fn cozo_comparator_v1(a: &[u8], b: &[u8]) -> Ordering { + cmp_keys(&mut ByteArrayParser { bytes: a, current: 0 }, + &mut ByteArrayParser { bytes: b, current: 0 }) +} + pub fn cmp_data<'a>(pa: &mut ByteArrayParser<'a>, pb: &mut ByteArrayParser<'a>) -> Ordering { loop { match (pa.at_end(), pb.at_end()) {