diff --git a/src/db.rs b/src/db.rs index 7c8e98e5..3f184083 100644 --- a/src/db.rs +++ b/src/db.rs @@ -5,3 +5,4 @@ pub mod mutation; pub mod table; pub mod plan; pub mod ddl; +pub mod env; diff --git a/src/db/env.rs b/src/db/env.rs new file mode 100644 index 00000000..038f8e21 --- /dev/null +++ b/src/db/env.rs @@ -0,0 +1,217 @@ +use std::collections::BTreeMap; +use cozorocks::SlicePtr; +use crate::db::engine::Session; +use crate::relation::value::Value; +use crate::error::{CozoError, Result}; +use crate::relation::data::DataKind; +use crate::relation::tuple::{OwnTuple, Tuple}; + +/// # layouts for sector 0 +/// +/// `[Null]`: stores information about table_ids +/// `[Text, Int]`: contains definable data and depth info +/// `[Int, Text]`: inverted index for depth info +/// `[Null, Text, Int, Int, Text]` inverted index for related tables +/// `[Null, Int, Text, Int, Text]` inverted index for related tables +/// `[True, Int]` table info, value is key + + +// type TableEnv = BTreeMap; +#[derive(Debug, Default)] +pub struct TableEnv<'a> { + pub parent: Option<&'a TableEnv<'a>>, + pub current: BTreeMap, +} + +impl<'a> TableEnv<'a> { + pub fn derive(&'a self) -> TableEnv<'a> { + TableEnv { + parent: Some(self), + current: Default::default(), + } + } + + pub fn resolve(&self, key: &str) -> Option<&()> { + match self.current.get(key) { + None => match self.parent { + None => None, + Some(t) => t.resolve(key) + } + v => v + } + } +} + + +impl<'s> Session<'s> { + pub fn define_variable(&mut self, name: &str, val: &Value, in_root: bool) -> Result<()> { + let mut data = Tuple::with_data_prefix(DataKind::Value); + data.push_value(val); + self.define_data(name, data, in_root) + } + + pub fn define_data(&mut self, name: &str, data: OwnTuple, in_root: bool) -> Result<()> { + let key = self.encode_definable_key(name, in_root); + if in_root { + self.txn.put(true, &self.perm_cf, key, data)?; + } else { + let mut ikey = Tuple::with_null_prefix(); + ikey.push_int(self.stack_depth as i64); + ikey.push_str(name); + self.txn.put(false, &self.temp_cf, key, data)?; + self.txn.put(false, &self.temp_cf, ikey, "")?; + } + Ok(()) + } + + pub fn key_exists(&self, key: &OwnTuple, in_root: bool) -> Result { + let res = self.txn.get(in_root, if in_root { &self.perm_cf } else { &self.temp_cf }, key)?; + Ok(res.is_some()) + } + + pub fn del_key(&self, key: &OwnTuple, in_root: bool) -> Result<()> { + self.txn.del(in_root, if in_root { &self.perm_cf } else { &self.temp_cf }, key)?; + Ok(()) + } + + pub fn define_raw_key(&self, key: &OwnTuple, value: Option<&OwnTuple>, in_root: bool) -> Result<()> { + if in_root { + match value { + None => { + self.txn.put(true, &self.perm_cf, key, "")?; + } + Some(v) => { + self.txn.put(true, &self.perm_cf, key, &v)?; + } + } + } else { + match value { + None => { + self.txn.put(false, &self.temp_cf, key, "")?; + } + Some(v) => { + self.txn.put(false, &self.temp_cf, key, &v)?; + } + } + } + Ok(()) + } + + pub fn resolve_value(&self, name: &str) -> Result> { + match self.resolve(name)? { + None => Ok(None), + Some(t) => { + match t.data_kind()? { + DataKind::Value => Ok(Some(t.get(0) + .ok_or_else(|| CozoError::LogicError("Corrupt".to_string()))? + .to_static())), + k => Err(CozoError::UnexpectedDataKind(k)) + } + } + } + } + pub fn get_stack_depth(&self) -> i32 { + self.stack_depth + } + + pub fn push_env(&mut self) -> Result<()> { + if self.stack_depth <= -1024 { + return Err(CozoError::LogicError("Stack overflow in env".to_string())); + } + self.stack_depth -= 1; + Ok(()) + } + + pub fn pop_env(&mut self) -> Result<()> { + // Remove all stuff starting with the stack depth from the temp session + let mut prefix = Tuple::with_null_prefix(); + prefix.push_int(self.stack_depth as i64); + let it = self.txn.iterator(false, &self.temp_cf); + it.seek(&prefix); + let mut to_delete = vec![]; + for val in it.keys() { + let cur = Tuple::new(val); + if cur.starts_with(&prefix) { + if let Some(name) = cur.get(1) { + let mut ikey = Tuple::with_null_prefix(); + ikey.push_value(&name); + ikey.push_int(self.stack_depth as i64); + + let data = self.txn.get(false, &self.temp_cf, &ikey)? + .ok_or_else(|| CozoError::LogicError("Bad format for ikey".to_string()))?; + let data = Tuple::new(data); + match data.data_kind()? { + DataKind::Node | + DataKind::Edge | + DataKind::Assoc | + DataKind::Index => { + let id = data.get_int(1).ok_or_else(|| CozoError::LogicError("Bad table index".to_string()))?; + let mut rkey = Tuple::with_null_prefix(); + rkey.push_bool(true); + rkey.push_int(id); + self.txn.del(false, &self.temp_cf, rkey)?; + let range_start = Tuple::with_prefix(id as u32); + let mut range_end = Tuple::with_prefix(id as u32); + range_end.seal_with_sentinel(); + self.txn.del_range(&self.temp_cf, range_start, range_end)?; + } + _ => {} + } + to_delete.push(cur.data.as_ref().to_vec()); + to_delete.push(ikey.data.to_vec()); + } + } else { + break; + } + } + + let mut prefix = Tuple::with_null_prefix(); + prefix.push_null(); + prefix.push_int(self.stack_depth as i64); + let it = self.txn.iterator(false, &self.temp_cf); + it.seek(&prefix); + for val in it.keys() { + let cur = Tuple::new(val); + if cur.starts_with(&prefix) { + let mut ikey = Tuple::with_prefix(cur.get_prefix()); + ikey.push_null(); + ikey.push_str(cur.get_text(2).unwrap()); + ikey.push_int(cur.get_int(1).unwrap()); + for k in cur.iter().skip(3) { + ikey.push_value(&k); + } + + to_delete.push(cur.data.as_ref().to_vec()); + to_delete.push(ikey.data.to_vec()); + } else { + break; + } + } + + if self.stack_depth != 0 { + self.stack_depth += 1; + } + + for d in to_delete { + self.txn.del(false, &self.temp_cf, &d)?; + } + + Ok(()) + } + + pub fn resolve(&self, name: &str) -> Result>> { + let mut tuple = Tuple::with_null_prefix(); + tuple.push_str(name); + let it = self.txn.iterator(false, &self.temp_cf); + it.seek(&tuple); + if let Some((tk, vk)) = it.pair() { + let k = Tuple::new(tk); + if k.starts_with(&tuple) { + return Ok(Some(Tuple::new(vk))); + } + } + let root_key = self.encode_definable_key(name, true); + let res = self.txn.get(true, &self.perm_cf, root_key).map(|v| v.map(Tuple::new))?; + Ok(res) + } +} \ No newline at end of file diff --git a/src/db/eval.rs b/src/db/eval.rs index cd66ef53..41568556 100644 --- a/src/db/eval.rs +++ b/src/db/eval.rs @@ -1,116 +1,13 @@ use std::borrow::Cow; use std::collections::{BTreeMap}; -use cozorocks::{SlicePtr}; use crate::db::engine::{Session}; -use crate::relation::tuple::{OwnTuple, Tuple}; +use crate::db::env::TableEnv; use crate::relation::value::{Value}; use crate::error::{CozoError, Result}; use crate::error::CozoError::LogicError; -use crate::relation::data::DataKind; use crate::relation::value; -/// # layouts for sector 0 -/// -/// `[Null]`: stores information about table_ids -/// `[Text, Int]`: contains definable data and depth info -/// `[Int, Text]`: inverted index for depth info -/// `[Null, Text, Int, Int, Text]` inverted index for related tables -/// `[Null, Int, Text, Int, Text]` inverted index for related tables -/// `[True, Int]` table info, value is key - -// type TableEnv = BTreeMap; -#[derive(Debug, Default)] -pub struct TableEnv<'a> { - pub parent: Option<&'a TableEnv<'a>>, - pub current: BTreeMap, -} - -impl<'a> TableEnv<'a> { - pub fn derive(&'a self) -> TableEnv<'a> { - TableEnv { - parent: Some(self), - current: Default::default(), - } - } - - pub fn resolve(&self, key: &str) -> Option<&()> { - match self.current.get(key) { - None => match self.parent { - None => None, - Some(t) => t.resolve(key) - } - v => v - } - } -} - impl<'s> Session<'s> { - pub fn define_variable(&mut self, name: &str, val: &Value, in_root: bool) -> Result<()> { - let mut data = Tuple::with_data_prefix(DataKind::Value); - data.push_value(val); - self.define_data(name, data, in_root) - } - - pub fn define_data(&mut self, name: &str, data: OwnTuple, in_root: bool) -> Result<()> { - let key = self.encode_definable_key(name, in_root); - if in_root { - self.txn.put(true, &self.perm_cf, key, data)?; - } else { - let mut ikey = Tuple::with_null_prefix(); - ikey.push_int(self.stack_depth as i64); - ikey.push_str(name); - self.txn.put(false, &self.temp_cf, key, data)?; - self.txn.put(false, &self.temp_cf, ikey, "")?; - } - Ok(()) - } - - pub fn key_exists(&self, key: &OwnTuple, in_root: bool) -> Result { - let res = self.txn.get(in_root, if in_root { &self.perm_cf } else { &self.temp_cf }, key)?; - Ok(res.is_some()) - } - - pub fn del_key(&self, key: &OwnTuple, in_root: bool) -> Result<()> { - self.txn.del(in_root, if in_root { &self.perm_cf } else { &self.temp_cf }, key)?; - Ok(()) - } - - pub fn define_raw_key(&self, key: &OwnTuple, value: Option<&OwnTuple>, in_root: bool) -> Result<()> { - if in_root { - match value { - None => { - self.txn.put(true, &self.perm_cf, key, "")?; - } - Some(v) => { - self.txn.put(true, &self.perm_cf, key, &v)?; - } - } - } else { - match value { - None => { - self.txn.put(false, &self.temp_cf, key, "")?; - } - Some(v) => { - self.txn.put(false, &self.temp_cf, key, &v)?; - } - } - } - Ok(()) - } - - fn resolve_value(&self, name: &str) -> Result> { - match self.resolve(name)? { - None => Ok(None), - Some(t) => { - match t.data_kind()? { - DataKind::Value => Ok(Some(t.get(0) - .ok_or_else(|| CozoError::LogicError("Corrupt".to_string()))? - .to_static())), - k => Err(CozoError::UnexpectedDataKind(k)) - } - } - } - } pub fn partial_eval<'a>(&self, value: Value<'a>, params: &BTreeMap>, table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { match value { @@ -740,111 +637,6 @@ impl<'s> Session<'s> { Err(Err(e)) => Err(e) } } - - pub fn get_stack_depth(&self) -> i32 { - self.stack_depth - } - - pub fn push_env(&mut self) -> Result<()> { - if self.stack_depth <= -1024 { - return Err(CozoError::LogicError("Stack overflow in env".to_string())); - } - self.stack_depth -= 1; - Ok(()) - } - - pub fn pop_env(&mut self) -> Result<()> { - // Remove all stuff starting with the stack depth from the temp session - let mut prefix = Tuple::with_null_prefix(); - prefix.push_int(self.stack_depth as i64); - let it = self.txn.iterator(false, &self.temp_cf); - it.seek(&prefix); - let mut to_delete = vec![]; - for val in it.keys() { - let cur = Tuple::new(val); - if cur.starts_with(&prefix) { - if let Some(name) = cur.get(1) { - let mut ikey = Tuple::with_null_prefix(); - ikey.push_value(&name); - ikey.push_int(self.stack_depth as i64); - - let data = self.txn.get(false, &self.temp_cf, &ikey)? - .ok_or_else(|| CozoError::LogicError("Bad format for ikey".to_string()))?; - let data = Tuple::new(data); - match data.data_kind()? { - DataKind::Node | - DataKind::Edge | - DataKind::Assoc | - DataKind::Index => { - let id = data.get_int(1).ok_or_else(|| CozoError::LogicError("Bad table index".to_string()))?; - let mut rkey = Tuple::with_null_prefix(); - rkey.push_bool(true); - rkey.push_int(id); - self.txn.del(false, &self.temp_cf, rkey)?; - let range_start = Tuple::with_prefix(id as u32); - let mut range_end = Tuple::with_prefix(id as u32); - range_end.seal_with_sentinel(); - self.txn.del_range(&self.temp_cf, range_start, range_end)?; - } - _ => {} - } - to_delete.push(cur.data.as_ref().to_vec()); - to_delete.push(ikey.data.to_vec()); - } - } else { - break; - } - } - - let mut prefix = Tuple::with_null_prefix(); - prefix.push_null(); - prefix.push_int(self.stack_depth as i64); - let it = self.txn.iterator(false, &self.temp_cf); - it.seek(&prefix); - for val in it.keys() { - let cur = Tuple::new(val); - if cur.starts_with(&prefix) { - let mut ikey = Tuple::with_prefix(cur.get_prefix()); - ikey.push_null(); - ikey.push_str(cur.get_text(2).unwrap()); - ikey.push_int(cur.get_int(1).unwrap()); - for k in cur.iter().skip(3) { - ikey.push_value(&k); - } - - to_delete.push(cur.data.as_ref().to_vec()); - to_delete.push(ikey.data.to_vec()); - } else { - break; - } - } - - if self.stack_depth != 0 { - self.stack_depth += 1; - } - - for d in to_delete { - self.txn.del(false, &self.temp_cf, &d)?; - } - - Ok(()) - } - - pub fn resolve(&self, name: &str) -> Result>> { - let mut tuple = Tuple::with_null_prefix(); - tuple.push_str(name); - let it = self.txn.iterator(false, &self.temp_cf); - it.seek(&tuple); - if let Some((tk, vk)) = it.pair() { - let k = Tuple::new(tk); - if k.starts_with(&tuple) { - return Ok(Some(Tuple::new(vk))); - } - } - let root_key = self.encode_definable_key(name, true); - let res = self.txn.get(true, &self.perm_cf, root_key).map(|v| v.map(Tuple::new))?; - Ok(res) - } } @@ -855,6 +647,7 @@ mod tests { use crate::parser::{Parser, Rule}; use pest::Parser as PestParser; use crate::db::engine::Engine; + use crate::relation::tuple::Tuple; #[test] fn node() {