remove environment nonsense

main
Ziyang Hu 2 years ago
parent 9855b1d537
commit eceab71fcd

@ -201,7 +201,6 @@ pub enum SessionStatus {
#[cfg(test)]
mod tests {
use std::{fs, thread};
use crate::db::eval::Environment;
use crate::relation::tuple::Tuple;
use super::*;

@ -22,21 +22,12 @@ use crate::relation::value;
/// `[Null, Int, Text, Int, Text]` inverted index for related tables
/// `[True, Int]` table info, value is key
pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
fn get_next_storage_id(&mut self, in_root: bool) -> Result<i64>;
fn get_stack_depth(&self) -> i32;
fn push_env(&mut self) -> Result<()>;
fn pop_env(&mut self) -> Result<()>;
fn set_param(&mut self, name: &str, val: &'t str);
fn define_variable(&mut self, name: &str, val: &Value, in_root: bool) -> Result<()> {
impl<'s, 't> Session<'s, 't> {
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)
}
fn table_data(&self, id: i64, in_root: bool) -> Result<Option<Tuple<T>>>;
fn resolve(&self, name: &str) -> Result<Option<Tuple<T>>>;
fn resolve_related_tables(&self, name: &str) -> Result<Vec<(String, Tuple<SlicePtr>)>>;
fn resolve_param(&self, name: &str) -> Result<Value>;
fn resolve_value(&self, name: &str) -> Result<Option<Value>> {
if name.starts_with('&') {
self.resolve_param(name).map(|v| Some(v.clone()))
@ -54,11 +45,6 @@ pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
}
}
}
fn delete_defined(&mut self, name: &str, in_root: bool) -> Result<()>;
fn define_data(&mut self, name: &str, data: OwnTuple, in_root: bool) -> Result<()>;
fn key_exists(&self, key: &OwnTuple, in_root: bool) -> Result<bool>;
fn del_key(&self, key: &OwnTuple, in_root: bool) -> Result<()>;
fn define_raw_key(&self, key: &OwnTuple, value: Option<&OwnTuple>, in_root: bool) -> Result<()>;
fn encode_definable_key(&self, name: &str, in_root: bool) -> OwnTuple {
let depth_code = if in_root { 0 } else { self.get_stack_depth() as i64 };
let mut tuple = Tuple::with_null_prefix();
@ -231,7 +217,7 @@ pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
Ok((name, tuple, index_data))
}
fn extract_table_id(src_tbl: Tuple<T>) -> Result<(DataKind, bool, i64)> {
fn extract_table_id<T: AsRef<[u8]>>(src_tbl: Tuple<T>) -> Result<(DataKind, bool, i64)> {
let kind = src_tbl.data_kind()?;
match kind {
DataKind::Data | DataKind::Value | DataKind::Type => return Err(CozoError::UnexpectedDataKind(kind)),
@ -252,7 +238,7 @@ pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
tuple.push_null(); // TODO default values for cols
Ok((name, tuple, vec![]))
}
fn run_definition(&mut self, pair: Pair<Rule>) -> Result<()> {
pub fn run_definition(&mut self, pair: Pair<Rule>) -> Result<()> {
let in_root = match pair.as_rule() {
Rule::global_def => true,
Rule::local_def => false,
@ -276,7 +262,7 @@ pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
}
self.define_data(&name, tuple, in_root)
}
fn partial_eval<'a>(&self, value: Value<'a>) -> Result<(bool, Value<'a>)> {
pub fn partial_eval<'a>(&self, value: Value<'a>) -> Result<(bool, Value<'a>)> {
match value {
v @ (Value::Null |
Value::Bool(_) |
@ -722,10 +708,8 @@ pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
Err(Err(e)) => Err(e)
}
}
}
impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
fn get_next_storage_id(&mut self, in_root: bool) -> Result<i64> {
// TODO: deal with wrapping problem
let mut key_entry = Tuple::with_null_prefix();
@ -756,7 +740,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
self.stack_depth
}
fn push_env(&mut self) -> Result<()> {
pub fn push_env(&mut self) -> Result<()> {
if self.stack_depth <= -1024 {
return Err(CozoError::LogicError("Stack overflow in env".to_string()));
}
@ -764,7 +748,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
Ok(())
}
fn pop_env(&mut self) -> Result<()> {
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);
@ -845,7 +829,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
self.params.insert(name.to_string(), val);
}
fn table_data(&self, id: i64, in_root: bool) -> Result<Option<Tuple<SlicePtr>>> {
pub fn table_data(&self, id: i64, in_root: bool) -> Result<Option<Tuple<SlicePtr>>> {
let mut key = Tuple::with_null_prefix();
key.push_bool(true);
key.push_int(id);
@ -858,7 +842,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
}
}
fn resolve(&self, name: &str) -> Result<Option<Tuple<SlicePtr>>> {
pub fn resolve(&self, name: &str) -> Result<Option<Tuple<SlicePtr>>> {
let mut tuple = Tuple::with_null_prefix();
tuple.push_str(name);
let it = self.txn.iterator(false, &self.temp_cf);
@ -874,7 +858,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
Ok(res)
}
fn resolve_related_tables(&self, name: &str) -> Result<Vec<(String, Tuple<SlicePtr>)>> {
pub fn resolve_related_tables(&self, name: &str) -> Result<Vec<(String, Tuple<SlicePtr>)>> {
let mut prefix = Tuple::with_prefix(0);
prefix.push_null();
prefix.push_str(name);
@ -956,7 +940,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
Ok(())
}
fn key_exists(&self, key: &OwnTuple, in_root: bool) -> Result<bool> {
pub fn key_exists(&self, key: &OwnTuple, in_root: bool) -> Result<bool> {
let res = self.txn.get(in_root, if in_root { &self.perm_cf } else { &self.temp_cf }, key)?;
Ok(res.is_some())
}
@ -966,7 +950,7 @@ impl<'a, 't> Environment<'t, SlicePtr> for Session<'a, 't> {
Ok(())
}
fn define_raw_key(&self, key: &OwnTuple, value: Option<&OwnTuple>, in_root: bool) -> Result<()> {
pub fn define_raw_key(&self, key: &OwnTuple, value: Option<&OwnTuple>, in_root: bool) -> Result<()> {
if in_root {
match value {
None => {

@ -4,7 +4,6 @@ use std::collections::{BTreeMap, HashSet};
use std::rc::Rc;
use pest::iterators::Pair;
use crate::db::engine::Session;
use crate::db::eval::Environment;
use crate::db::table::TableInfo;
use crate::error::CozoError::LogicError;
use crate::error::{CozoError, Result};
@ -117,7 +116,7 @@ impl<'a, 'b, 't> MutationManager<'a, 'b, 't> {
match table_info.kind {
DataKind::Node => {
key_tuple = Tuple::with_prefix(table_info.table_id as u32);
key_tuple = Tuple::with_prefix(table_info.table_id.id as u32);
for (k, v) in &table_info.key_typing {
let raw = val_map.remove(k.as_str()).unwrap_or(Value::Null);
let processed = v.coerce(raw)?;
@ -130,17 +129,17 @@ impl<'a, 'b, 't> MutationManager<'a, 'b, 't> {
let processed = v.coerce(raw)?;
val_tuple.push_value(&processed);
}
if error_on_existing && self.sess.key_exists(&key_tuple, table_info.in_root)? {
if error_on_existing && self.sess.key_exists(&key_tuple, table_info.table_id.in_root)? {
return Err(CozoError::KeyConflict(key_tuple));
}
self.sess.define_raw_key(&key_tuple, Some(&val_tuple), table_info.in_root)?;
self.sess.define_raw_key(&key_tuple, Some(&val_tuple), table_info.table_id.in_root)?;
}
DataKind::Edge => {
key_tuple = Tuple::with_prefix(table_info.table_id as u32);
key_tuple.push_int(table_info.src_table_id);
key_tuple = Tuple::with_prefix(table_info.table_id.id as u32);
key_tuple.push_int(table_info.src_table_id.id);
let mut ikey_tuple = Tuple::with_prefix(table_info.table_id as u32);
ikey_tuple.push_int(table_info.dst_table_id);
let mut ikey_tuple = Tuple::with_prefix(table_info.table_id.id as u32);
ikey_tuple.push_int(table_info.dst_table_id.id);
let mut val_tuple = Tuple::with_data_prefix(DataKind::Data);
@ -196,11 +195,11 @@ impl<'a, 'b, 't> MutationManager<'a, 'b, 't> {
let processed = v.coerce(raw)?;
val_tuple.push_value(&processed);
}
if error_on_existing && self.sess.key_exists(&key_tuple, table_info.in_root)? {
if error_on_existing && self.sess.key_exists(&key_tuple, table_info.table_id.in_root)? {
return Err(CozoError::KeyConflict(key_tuple));
}
self.sess.define_raw_key(&key_tuple, Some(&val_tuple), table_info.in_root)?;
self.sess.define_raw_key(&ikey_tuple, Some(&key_tuple), table_info.in_root)?;
self.sess.define_raw_key(&key_tuple, Some(&val_tuple), table_info.table_id.in_root)?;
self.sess.define_raw_key(&ikey_tuple, Some(&key_tuple), table_info.table_id.in_root)?;
}
_ => unreachable!()
}
@ -215,8 +214,8 @@ impl<'a, 'b, 't> MutationManager<'a, 'b, 't> {
let processed = v.coerce(raw)?;
val_tuple.push_value(&processed);
}
key_tuple.overwrite_prefix(assoc.table_id as u32);
self.sess.define_raw_key(&key_tuple, Some(&val_tuple), assoc.in_root)?;
key_tuple.overwrite_prefix(assoc.table_id.id as u32);
self.sess.define_raw_key(&key_tuple, Some(&val_tuple), assoc.table_id.in_root)?;
}
}
Ok(())
@ -229,7 +228,6 @@ mod tests {
use std::time::Instant;
use pest::Parser as PestParser;
use crate::db::engine::Engine;
use crate::db::eval::Environment;
use crate::parser::{Parser, Rule};
use crate::relation::tuple::Tuple;

@ -41,7 +41,7 @@ use crate::db::engine::Session;
use crate::db::table::TableInfo;
use crate::error::CozoError::LogicError;
use crate::parser::Rule;
use crate::error::Result;
use crate::error::{CozoError, Result};
use crate::parser::text_identifier::build_name_in_def;
use crate::relation::data::DataKind;
@ -74,7 +74,7 @@ pub struct EdgeOrNodeEl {
}
impl<'a, 't> Session<'a, 't> {
pub fn parse_from_pattern(&self, pair: Pair<Rule>) -> Result<()> {
pub fn parse_from_pattern(&self, pair: Pair<Rule>) -> Result<Vec<FromEl>> {
let res: Result<Vec<_>> = pair.into_inner().map(|p| {
match p.as_rule() {
Rule::simple_from_pattern => self.parse_simple_from_pattern(p),
@ -82,10 +82,10 @@ impl<'a, 't> Session<'a, 't> {
_ => unreachable!()
}
}).collect();
Ok(())
res
}
fn parse_simple_from_pattern(&self, pair: Pair<Rule>) -> Result<()> {
fn parse_simple_from_pattern(&self, pair: Pair<Rule>) -> Result<FromEl> {
let mut pairs = pair.into_inner();
let name = pairs.next().unwrap().as_str();
if name.starts_with('_') {
@ -94,11 +94,10 @@ impl<'a, 't> Session<'a, 't> {
let table_name = build_name_in_def(pairs.next().unwrap(), true)?;
let table_info = self.get_table_info(&table_name)?;
let ret = FromEl::Simple(Box::new(SimpleFromEl { binding: name.to_string(), table: table_name, info: table_info }));
println!("{:#?}", ret);
Ok(())
Ok(ret)
}
fn parse_node_edge_pattern(&self, pair: Pair<Rule>) -> Result<()> {
fn parse_node_edge_pattern(&self, pair: Pair<Rule>) -> Result<FromEl> {
let res: Result<Vec<_>> = pair.into_inner().map(|p| {
match p.as_rule() {
Rule::node_pattern => self.parse_node_pattern(p),
@ -107,9 +106,30 @@ impl<'a, 't> Session<'a, 't> {
_ => unreachable!()
}
}).collect();
// TODO check the chain connects!
println!("{:#?}", res);
Ok(())
let res = res?;
let connects = res.windows(2).all(|v| {
let left = &v[0];
let right = &v[1];
match (&left.kind, &right.kind) {
(EdgeOrNodeKind::FwdEdge, EdgeOrNodeKind::Node) => {
left.info.dst_table_id == right.info.table_id
}
(EdgeOrNodeKind::BwdEdge, EdgeOrNodeKind::Node) => {
left.info.src_table_id == right.info.table_id
}
(EdgeOrNodeKind::Node, EdgeOrNodeKind::FwdEdge) => {
left.info.table_id == right.info.src_table_id
}
(EdgeOrNodeKind::Node, EdgeOrNodeKind::BwdEdge) => {
left.info.table_id == right.info.dst_table_id
}
_ => unreachable!()
}
});
if !connects {
return Err(CozoError::LogicError("Chain does not connect".to_string()));
}
Ok(FromEl::Chain(res))
}
fn parse_node_pattern(&self, pair: Pair<Rule>) -> Result<EdgeOrNodeEl> {
@ -164,7 +184,6 @@ mod tests {
use crate::parser::{Parser, Rule};
use pest::Parser as PestParser;
use crate::db::engine::Engine;
use crate::db::eval::Environment;
#[test]
fn parse_patterns() {
@ -184,6 +203,10 @@ mod tests {
relation: ?Text
}
create node Z {
*id: Text
}
create assoc WorkInfo : Person {
work_id: Int
}
@ -205,6 +228,11 @@ mod tests {
let parsed = Parser::parse(Rule::from_pattern, s).unwrap().next().unwrap();
assert_eq!(parsed.as_rule(), Rule::from_pattern);
sess.parse_from_pattern(parsed).unwrap();
let s = "from a:Friend, (b:Person)-[:Friend]->(c:Z), x:Person";
let parsed = Parser::parse(Rule::from_pattern, s).unwrap().next().unwrap();
assert_eq!(parsed.as_rule(), Rule::from_pattern);
assert!(sess.parse_from_pattern(parsed).is_err());
}
drop(engine);
let _ = fs::remove_dir_all(db_path);

@ -1,20 +1,37 @@
use std::collections::HashSet;
use crate::db::engine::Session;
use crate::db::eval::Environment;
use crate::error::{CozoError, Result};
use crate::error::CozoError::LogicError;
use crate::relation::data::DataKind;
use crate::relation::typing::Typing;
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub struct TableId {
pub in_root: bool,
pub id: i64,
}
impl TableId {
pub fn new(in_root: bool, id: i64) -> Self {
TableId { in_root, id }
}
pub fn is_valid(&self) -> bool {
self.id >= 0
}
}
impl Default for TableId {
fn default() -> Self {
TableId { in_root: false, id: -1 }
}
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct TableInfo {
pub kind: DataKind,
pub table_id: i64,
pub src_table_id: i64,
pub dst_table_id: i64,
pub src_in_root: bool,
pub dst_in_root: bool,
pub in_root: bool,
pub table_id: TableId,
pub src_table_id: TableId,
pub dst_table_id: TableId,
pub data_keys: HashSet<String>,
pub key_typing: Vec<(String, Typing)>,
pub val_typing: Vec<(String, Typing)>,
@ -38,21 +55,19 @@ impl<'a, 't> Session<'a, 't> {
.extract_named_tuple().ok_or_else(|| CozoError::LogicError("Corrupt data".to_string()))?;
let in_root = tpl.get_bool(0).ok_or_else(|| CozoError::LogicError("Cannot extract in root".to_string()))?;
let table_id = tpl.get_int(1).ok_or_else(|| CozoError::LogicError("Cannot extract in root".to_string()))?;
let table_id = TableId::new(in_root, table_id);
TableInfo {
kind: DataKind::Node,
table_id,
in_root,
src_table_id: -1,
dst_table_id: -1,
src_in_root: false,
src_table_id: Default::default(),
dst_table_id: Default::default(),
data_keys: val_extractor.iter().map(|(k, _)| k.clone()).collect(),
key_typing: key_extractor,
val_typing: val_extractor,
src_key_typing: vec![],
dst_key_typing: vec![],
associates: vec![],
dst_in_root: false
}
}
DataKind::Edge => {
@ -66,10 +81,12 @@ impl<'a, 't> Session<'a, 't> {
.ok_or_else(|| CozoError::LogicError("Src in root extraction failed".to_string()))?;
let src_id = tpl.get_int(3)
.ok_or_else(|| CozoError::LogicError("Src id extraction failed".to_string()))?;
let src_table_id = TableId::new(src_in_root, src_id);
let dst_in_root = tpl.get_bool(4)
.ok_or_else(|| CozoError::LogicError("Dst in root extraction failed".to_string()))?;
let dst_id = tpl.get_int(5)
.ok_or_else(|| CozoError::LogicError("Dst id extraction failed".to_string()))?;
let dst_table_id = TableId::new(dst_in_root, dst_id);
let src = self.table_data(src_id, src_in_root)?
.ok_or_else(|| CozoError::LogicError("Getting src failed".to_string()))?;
let src_key = Typing::try_from(src.get_text(2)
@ -86,21 +103,19 @@ impl<'a, 't> Session<'a, 't> {
let in_root = tpl.get_bool(0).ok_or_else(|| CozoError::LogicError("Cannot extract in root".to_string()))?;
let table_id = tpl.get_int(1).ok_or_else(|| CozoError::LogicError("Cannot extract in root".to_string()))?;
let table_id = TableId::new(in_root, table_id);
TableInfo {
kind: DataKind::Edge,
table_id,
in_root,
src_table_id: src_id,
dst_table_id: dst_id,
src_in_root,
src_table_id,
dst_table_id,
data_keys: val_extractor.iter().map(|(k, _)| k.clone()).collect(),
key_typing: other_key_extractor,
val_typing: val_extractor,
src_key_typing,
dst_key_typing,
associates: vec![],
dst_in_root
}
}
_ => return Err(LogicError("Cannot insert into non-tables".to_string()))
@ -113,21 +128,19 @@ impl<'a, 't> Session<'a, 't> {
.extract_named_tuple().ok_or_else(|| CozoError::LogicError("Corrupt data".to_string()))?;
let in_root = d.get_bool(0).ok_or_else(|| CozoError::LogicError("Cannot extract in root".to_string()))?;
let table_id = d.get_int(1).ok_or_else(|| CozoError::LogicError("Cannot extract in root".to_string()))?;
let table_id = TableId::new(in_root, table_id);
let coercer = TableInfo {
kind: DataKind::Assoc,
table_id,
in_root,
src_table_id: -1,
dst_table_id: -1,
src_in_root: false,
src_table_id: Default::default(),
dst_table_id: Default::default(),
data_keys: t.iter().map(|(k, _)| k.clone()).collect(),
key_typing: vec![],
val_typing: t,
src_key_typing: vec![],
dst_key_typing: vec![],
associates: vec![],
dst_in_root: false
};
main_coercer.associates.push(coercer);

@ -5,7 +5,6 @@ use crate::relation::value::Value;
use pest::Parser as PestParser;
use cozorocks::SlicePtr;
use crate::db::engine::Session;
use crate::db::eval::{Environment};
use crate::parser::Parser;
use crate::parser::Rule;
use crate::parser::text_identifier::build_name_in_def;
@ -66,7 +65,7 @@ impl Typing {
}
impl Typing {
pub fn from_pair<'t, T: AsRef<[u8]>, E: Environment<'t, T>>(pair: Pair<Rule>, env: Option<&E>) -> Result<Self> {
pub fn from_pair<'a, 't>(pair: Pair<Rule>, env: Option<&Session<'a, 't>>) -> Result<Self> {
Ok(match pair.as_rule() {
Rule::simple_type => match pair.as_str() {
"Any" => Typing::Any,
@ -194,7 +193,7 @@ impl TryFrom<&str> for Typing {
fn try_from(value: &str) -> Result<Self> {
let pair = Parser::parse(Rule::typing, value)?.next().unwrap();
Typing::from_pair::<SlicePtr, Session>(pair, None)
Typing::from_pair(pair, None)
}
}

Loading…
Cancel
Save