main
Ziyang Hu 2 years ago
parent 16d5dbb991
commit cb8239897b

@ -3,3 +3,5 @@ pub mod eval;
pub mod query;
pub mod mutation;
pub mod table;
pub mod plan;
pub mod ddl;

@ -0,0 +1,334 @@
use std::collections::HashSet;
use pest::iterators::{Pair, Pairs};
use cozorocks::SlicePtr;
use crate::db::engine::Session;
use crate::relation::tuple::{OwnTuple, Tuple};
use crate::relation::typing::Typing;
use crate::parser::Rule;
use crate::error::{CozoError, Result};
use crate::parser::text_identifier::build_name_in_def;
use crate::relation::data::DataKind;
use crate::relation::value::Value;
impl<'s> Session<'s> {
pub 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();
tuple.push_str(name);
tuple.push_int(depth_code);
tuple
}
fn parse_cols(&self, pair: Pair<Rule>) -> Result<(Typing, Typing)> {
let col_res = pair.into_inner().map(|p| {
let mut ps = p.into_inner();
let mut name_ps = ps.next().unwrap().into_inner();
let is_key;
let mut name_p = name_ps.next().unwrap();
match name_p.as_rule() {
Rule::key_marker => {
is_key = true;
name_p = name_ps.next().unwrap();
}
_ => { is_key = false }
}
let name = build_name_in_def(name_p, true)?;
let type_p = Typing::from_pair(ps.next().unwrap(), Some(self))?;
Ok((is_key, name, type_p))
}).collect::<Result<Vec<_>>>()?;
let all_names = col_res.iter().map(|(_, n, _)| n).collect::<HashSet<_>>();
if all_names.len() != col_res.len() {
return Err(CozoError::DuplicateNames(col_res.iter().map(|(_, n, _)| n.to_string()).collect::<Vec<_>>()));
}
let (keys, cols): (Vec<_>, Vec<_>) = col_res.iter().partition(|(is_key, _, _)| *is_key);
let keys_typing = Typing::NamedTuple(keys.iter().map(|(_, n, t)| (n.to_string(), t.clone())).collect());
let vals_typing = Typing::NamedTuple(cols.iter().map(|(_, n, t)| (n.to_string(), t.clone())).collect());
Ok((keys_typing, vals_typing))
}
fn parse_definition(&self, pair: Pair<Rule>, in_root: bool) -> Result<(bool, (String, OwnTuple, Vec<OwnTuple>))> {
Ok(match pair.as_rule() {
Rule::node_def => (true, self.parse_node_def(pair.into_inner(), in_root)?),
Rule::edge_def => (true, self.parse_edge_def(pair.into_inner(), in_root)?),
Rule::associate_def => (true, self.parse_assoc_def(pair.into_inner(), in_root)?),
Rule::index_def => todo!(),
Rule::type_def => (false, self.parse_type_def(pair.into_inner(), in_root)?),
_ => unreachable!()
})
}
fn parse_assoc_def(&self, mut pairs: Pairs<Rule>, in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let src_name = build_name_in_def(pairs.next().unwrap(), true)?;
let src_tbl = match self.resolve(&src_name)? {
Some(res) => res,
None => return Err(CozoError::UndefinedType(src_name))
};
let (_kind, src_global, src_id) = Self::extract_table_id(src_tbl)?;
if in_root && !src_global {
return Err(CozoError::LogicError("Cannot have global edge with local nodes".to_string()));
}
let (keys_typing, vals_typing) = self.parse_cols(pairs.next().unwrap())?;
if keys_typing.to_string() != "{}" {
return Err(CozoError::LogicError("Cannot have keys in assoc".to_string()));
}
let mut tuple = Tuple::with_data_prefix(DataKind::Assoc);
tuple.push_bool(src_global);
tuple.push_int(src_id);
tuple.push_str(vals_typing.to_string());
let mut for_src = Tuple::with_prefix(0);
for_src.push_null();
for_src.push_str(&src_name);
for_src.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src.push_int(DataKind::Assoc as i64);
for_src.push_str(&name);
let mut for_src_i = Tuple::with_prefix(0);
for_src_i.push_null();
for_src_i.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src_i.push_str(&src_name);
for_src_i.push_int(DataKind::Assoc as i64);
for_src_i.push_str(&name);
Ok((name, tuple, vec![for_src, for_src_i]))
}
fn parse_type_def(&self, mut pairs: Pairs<Rule>, _in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let typ = Typing::from_pair(pairs.next().unwrap(), Some(self))?;
let mut data = Tuple::with_data_prefix(DataKind::Type);
data.push_str(typ.to_string());
Ok((name, data, vec![]))
}
fn parse_edge_def(&self, mut pairs: Pairs<Rule>, in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let src_name = build_name_in_def(pairs.next().unwrap(), true)?;
let src_tbl = match self.resolve(&src_name)? {
Some(res) => res,
None => return Err(CozoError::UndefinedType(src_name))
};
let (kind, src_global, src_id) = Self::extract_table_id(src_tbl)?;
if in_root && !src_global {
return Err(CozoError::LogicError("Cannot have global edge with local nodes".to_string()));
}
if kind != DataKind::Node {
return Err(CozoError::UnexpectedDataKind(kind));
}
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let dst_name = build_name_in_def(pairs.next().unwrap(), true)?;
let dst_tbl = match self.resolve(&dst_name)? {
Some(res) => res,
None => return Err(CozoError::UndefinedType(dst_name))
};
let (kind, dst_global, dst_id) = Self::extract_table_id(dst_tbl)?;
if in_root && !dst_global {
return Err(CozoError::LogicError("Cannot have global edge with local nodes".to_string()));
}
if kind != DataKind::Node {
return Err(CozoError::UnexpectedDataKind(kind));
}
let (keys_typing, vals_typing) = match pairs.next() {
Some(p) => self.parse_cols(p)?,
None => (Typing::NamedTuple(vec![]), Typing::NamedTuple(vec![]))
};
let mut tuple = Tuple::with_data_prefix(DataKind::Edge);
tuple.push_bool(src_global);
tuple.push_int(src_id);
tuple.push_bool(dst_global);
tuple.push_int(dst_id);
tuple.push_str(keys_typing.to_string());
tuple.push_str(vals_typing.to_string());
tuple.push_null(); // TODO default values for keys
tuple.push_null(); // TODO default values for cols
let mut index_data = Vec::with_capacity(2);
let mut for_src = Tuple::with_prefix(0);
for_src.push_null();
for_src.push_str(&src_name);
for_src.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src.push_int(DataKind::Edge as i64);
for_src.push_str(&name);
index_data.push(for_src);
let mut for_src_i = Tuple::with_prefix(0);
for_src_i.push_null();
for_src_i.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src_i.push_str(&src_name);
for_src_i.push_int(DataKind::Edge as i64);
for_src_i.push_str(&name);
index_data.push(for_src_i);
if dst_name != src_name {
let mut for_dst = Tuple::with_prefix(0);
for_dst.push_null();
for_dst.push_str(&dst_name);
for_dst.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_dst.push_int(DataKind::Edge as i64);
for_dst.push_str(&name);
index_data.push(for_dst);
let mut for_dst_i = Tuple::with_prefix(0);
for_dst_i.push_null();
for_dst_i.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_dst_i.push_str(&dst_name);
for_dst_i.push_int(DataKind::Edge as i64);
for_dst_i.push_str(&name);
index_data.push(for_dst_i);
}
Ok((name, tuple, index_data))
}
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)),
_ => {}
};
let is_global = src_tbl.get_bool(0).expect("Data corrupt");
let table_id = src_tbl.get_int(1).expect("Data corrupt");
Ok((kind, is_global, table_id))
}
fn parse_node_def(&self, mut pairs: Pairs<Rule>, _in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let col_pair = pairs.next().unwrap();
let (keys_typing, vals_typing) = self.parse_cols(col_pair)?;
let mut tuple = Tuple::with_data_prefix(DataKind::Node);
tuple.push_str(keys_typing.to_string());
tuple.push_str(vals_typing.to_string());
tuple.push_null(); // TODO default values for keys
tuple.push_null(); // TODO default values for cols
Ok((name, tuple, vec![]))
}
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,
r => panic!("Encountered definition with rule {:?}", r)
};
let (need_id, (name, mut tuple, assoc_defs)) = self.parse_definition(
pair.into_inner().next().unwrap(), in_root,
)?;
if need_id {
let id = self.get_next_storage_id(in_root)?;
tuple = tuple.insert_values_at(0, &[in_root.into(),
id.into()]);
let mut id_key = Tuple::with_null_prefix();
id_key.push_bool(true);
id_key.push_int(id);
self.define_raw_key(&id_key, Some(&tuple), in_root).unwrap();
}
for t in assoc_defs {
self.define_raw_key(&t, None, in_root).unwrap();
}
self.define_data(&name, tuple, in_root)
}
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();
key_entry.push_null();
let db_res = if in_root {
self.txn.get(true, &self.perm_cf, &key_entry)
} else {
self.txn.get(false, &self.temp_cf, &key_entry)
};
let u = if let Some(en) = db_res? {
if let Value::Int(u) = Tuple::new(en).get(0).unwrap() {
u
} else {
panic!("Unexpected value in storage id");
}
} else { 0 };
let mut new_data = Tuple::with_null_prefix();
new_data.push_int(u + 1);
if in_root {
self.txn.put(true, &self.perm_cf, key_entry, new_data)?;
} else {
self.txn.put(false, &self.temp_cf, key_entry, new_data)?;
}
Ok(u + 1)
}
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);
if in_root {
let data = self.txn.get(true, &self.perm_cf, key)?;
Ok(data.map(Tuple::new))
} else {
let data = self.txn.get(false, &self.temp_cf, key)?;
Ok(data.map(Tuple::new))
}
}
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);
let mut assocs = vec![];
let it = self.txn.iterator(true, &self.perm_cf);
it.seek(&prefix);
for val in it.keys() {
let cur = Tuple::new(val);
if !cur.starts_with(&prefix) {
break;
}
let name = cur.get_text(4).ok_or_else(|| CozoError::LogicError("Bad data".to_string()))?;
if let Some(data) = self.resolve(&name)? {
if data.data_kind()? == DataKind::Assoc {
assocs.push((name.to_string(), data));
}
}
}
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) {
break;
}
let name = cur.get_text(4).ok_or_else(|| CozoError::LogicError("Bad data".to_string()))?;
if let Some(data) = self.resolve(&name)? {
if data.data_kind()? == DataKind::Assoc {
assocs.push((name.to_string(), data));
}
}
}
Ok(assocs)
}
pub fn delete_defined(&mut self, name: &str, in_root: bool) -> Result<()> {
let key = self.encode_definable_key(name, in_root);
if in_root {
self.txn.del(true, &self.perm_cf, key)?;
} else {
let it = self.txn.iterator(false, &self.temp_cf);
it.seek(&key);
if let Some(found_key) = it.key() {
let found_key_tuple = Tuple::new(found_key);
if found_key_tuple.starts_with(&key) {
let mut ikey = Tuple::with_null_prefix();
ikey.push_value(&found_key_tuple.get(1).unwrap());
ikey.push_value(&found_key_tuple.get(0).unwrap());
self.txn.del(false, &self.temp_cf, found_key_tuple)?;
self.txn.del(false, &self.temp_cf, ikey)?;
}
}
}
// TODO cleanup if the thing deleted is a table
Ok(())
}
}

@ -1,16 +1,12 @@
use std::borrow::Cow;
use std::collections::{BTreeMap, HashSet};
use pest::iterators::{Pair, Pairs};
use std::collections::{BTreeMap};
use cozorocks::{SlicePtr};
use crate::db::engine::{Session};
use crate::relation::tuple::{OwnTuple, Tuple};
use crate::relation::typing::Typing;
use crate::relation::value::{Value};
use crate::error::{CozoError, Result};
use crate::error::CozoError::LogicError;
use crate::relation::data::DataKind;
use crate::parser::{Rule};
use crate::parser::text_identifier::build_name_in_def;
use crate::relation::value;
/// # layouts for sector 0
@ -54,6 +50,54 @@ impl<'s> Session<'s> {
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<bool> {
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<Option<Value>> {
match self.resolve(name)? {
None => Ok(None),
@ -67,223 +111,6 @@ impl<'s> Session<'s> {
}
}
}
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();
tuple.push_str(name);
tuple.push_int(depth_code);
tuple
}
fn parse_cols(&self, pair: Pair<Rule>) -> Result<(Typing, Typing)> {
let col_res = pair.into_inner().map(|p| {
let mut ps = p.into_inner();
let mut name_ps = ps.next().unwrap().into_inner();
let is_key;
let mut name_p = name_ps.next().unwrap();
match name_p.as_rule() {
Rule::key_marker => {
is_key = true;
name_p = name_ps.next().unwrap();
}
_ => { is_key = false }
}
let name = build_name_in_def(name_p, true)?;
let type_p = Typing::from_pair(ps.next().unwrap(), Some(self))?;
Ok((is_key, name, type_p))
}).collect::<Result<Vec<_>>>()?;
let all_names = col_res.iter().map(|(_, n, _)| n).collect::<HashSet<_>>();
if all_names.len() != col_res.len() {
return Err(CozoError::DuplicateNames(col_res.iter().map(|(_, n, _)| n.to_string()).collect::<Vec<_>>()));
}
let (keys, cols): (Vec<_>, Vec<_>) = col_res.iter().partition(|(is_key, _, _)| *is_key);
let keys_typing = Typing::NamedTuple(keys.iter().map(|(_, n, t)| (n.to_string(), t.clone())).collect());
let vals_typing = Typing::NamedTuple(cols.iter().map(|(_, n, t)| (n.to_string(), t.clone())).collect());
Ok((keys_typing, vals_typing))
}
fn parse_definition(&self, pair: Pair<Rule>, in_root: bool) -> Result<(bool, (String, OwnTuple, Vec<OwnTuple>))> {
Ok(match pair.as_rule() {
Rule::node_def => (true, self.parse_node_def(pair.into_inner(), in_root)?),
Rule::edge_def => (true, self.parse_edge_def(pair.into_inner(), in_root)?),
Rule::associate_def => (true, self.parse_assoc_def(pair.into_inner(), in_root)?),
Rule::index_def => todo!(),
Rule::type_def => (false, self.parse_type_def(pair.into_inner(), in_root)?),
_ => unreachable!()
})
}
fn parse_assoc_def(&self, mut pairs: Pairs<Rule>, in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let src_name = build_name_in_def(pairs.next().unwrap(), true)?;
let src_tbl = match self.resolve(&src_name)? {
Some(res) => res,
None => return Err(CozoError::UndefinedType(src_name))
};
let (_kind, src_global, src_id) = Self::extract_table_id(src_tbl)?;
if in_root && !src_global {
return Err(CozoError::LogicError("Cannot have global edge with local nodes".to_string()));
}
let (keys_typing, vals_typing) = self.parse_cols(pairs.next().unwrap())?;
if keys_typing.to_string() != "{}" {
return Err(CozoError::LogicError("Cannot have keys in assoc".to_string()));
}
let mut tuple = Tuple::with_data_prefix(DataKind::Assoc);
tuple.push_bool(src_global);
tuple.push_int(src_id);
tuple.push_str(vals_typing.to_string());
let mut for_src = Tuple::with_prefix(0);
for_src.push_null();
for_src.push_str(&src_name);
for_src.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src.push_int(DataKind::Assoc as i64);
for_src.push_str(&name);
let mut for_src_i = Tuple::with_prefix(0);
for_src_i.push_null();
for_src_i.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src_i.push_str(&src_name);
for_src_i.push_int(DataKind::Assoc as i64);
for_src_i.push_str(&name);
Ok((name, tuple, vec![for_src, for_src_i]))
}
fn parse_type_def(&self, mut pairs: Pairs<Rule>, _in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let typ = Typing::from_pair(pairs.next().unwrap(), Some(self))?;
let mut data = Tuple::with_data_prefix(DataKind::Type);
data.push_str(typ.to_string());
Ok((name, data, vec![]))
}
fn parse_edge_def(&self, mut pairs: Pairs<Rule>, in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let src_name = build_name_in_def(pairs.next().unwrap(), true)?;
let src_tbl = match self.resolve(&src_name)? {
Some(res) => res,
None => return Err(CozoError::UndefinedType(src_name))
};
let (kind, src_global, src_id) = Self::extract_table_id(src_tbl)?;
if in_root && !src_global {
return Err(CozoError::LogicError("Cannot have global edge with local nodes".to_string()));
}
if kind != DataKind::Node {
return Err(CozoError::UnexpectedDataKind(kind));
}
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let dst_name = build_name_in_def(pairs.next().unwrap(), true)?;
let dst_tbl = match self.resolve(&dst_name)? {
Some(res) => res,
None => return Err(CozoError::UndefinedType(dst_name))
};
let (kind, dst_global, dst_id) = Self::extract_table_id(dst_tbl)?;
if in_root && !dst_global {
return Err(CozoError::LogicError("Cannot have global edge with local nodes".to_string()));
}
if kind != DataKind::Node {
return Err(CozoError::UnexpectedDataKind(kind));
}
let (keys_typing, vals_typing) = match pairs.next() {
Some(p) => self.parse_cols(p)?,
None => (Typing::NamedTuple(vec![]), Typing::NamedTuple(vec![]))
};
let mut tuple = Tuple::with_data_prefix(DataKind::Edge);
tuple.push_bool(src_global);
tuple.push_int(src_id);
tuple.push_bool(dst_global);
tuple.push_int(dst_id);
tuple.push_str(keys_typing.to_string());
tuple.push_str(vals_typing.to_string());
tuple.push_null(); // TODO default values for keys
tuple.push_null(); // TODO default values for cols
let mut index_data = Vec::with_capacity(2);
let mut for_src = Tuple::with_prefix(0);
for_src.push_null();
for_src.push_str(&src_name);
for_src.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src.push_int(DataKind::Edge as i64);
for_src.push_str(&name);
index_data.push(for_src);
let mut for_src_i = Tuple::with_prefix(0);
for_src_i.push_null();
for_src_i.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_src_i.push_str(&src_name);
for_src_i.push_int(DataKind::Edge as i64);
for_src_i.push_str(&name);
index_data.push(for_src_i);
if dst_name != src_name {
let mut for_dst = Tuple::with_prefix(0);
for_dst.push_null();
for_dst.push_str(&dst_name);
for_dst.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_dst.push_int(DataKind::Edge as i64);
for_dst.push_str(&name);
index_data.push(for_dst);
let mut for_dst_i = Tuple::with_prefix(0);
for_dst_i.push_null();
for_dst_i.push_int(if in_root { 0 } else { self.get_stack_depth() as i64 });
for_dst_i.push_str(&dst_name);
for_dst_i.push_int(DataKind::Edge as i64);
for_dst_i.push_str(&name);
index_data.push(for_dst_i);
}
Ok((name, tuple, index_data))
}
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)),
_ => {}
};
let is_global = src_tbl.get_bool(0).expect("Data corrupt");
let table_id = src_tbl.get_int(1).expect("Data corrupt");
Ok((kind, is_global, table_id))
}
fn parse_node_def(&self, mut pairs: Pairs<Rule>, _in_root: bool) -> Result<(String, OwnTuple, Vec<OwnTuple>)> {
let name = build_name_in_def(pairs.next().unwrap(), true)?;
let col_pair = pairs.next().unwrap();
let (keys_typing, vals_typing) = self.parse_cols(col_pair)?;
let mut tuple = Tuple::with_data_prefix(DataKind::Node);
tuple.push_str(keys_typing.to_string());
tuple.push_str(vals_typing.to_string());
tuple.push_null(); // TODO default values for keys
tuple.push_null(); // TODO default values for cols
Ok((name, tuple, vec![]))
}
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,
r => panic!("Encountered definition with rule {:?}", r)
};
let (need_id, (name, mut tuple, assoc_defs)) = self.parse_definition(
pair.into_inner().next().unwrap(), in_root,
)?;
if need_id {
let id = self.get_next_storage_id(in_root)?;
tuple = tuple.insert_values_at(0, &[in_root.into(),
id.into()]);
let mut id_key = Tuple::with_null_prefix();
id_key.push_bool(true);
id_key.push_int(id);
self.define_raw_key(&id_key, Some(&tuple), in_root).unwrap();
}
for t in assoc_defs {
self.define_raw_key(&t, None, in_root).unwrap();
}
self.define_data(&name, tuple, in_root)
}
pub fn partial_eval<'a>(&self, value: Value<'a>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> {
match value {
@ -914,34 +741,7 @@ impl<'s> Session<'s> {
}
}
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();
key_entry.push_null();
let db_res = if in_root {
self.txn.get(true, &self.perm_cf, &key_entry)
} else {
self.txn.get(false, &self.temp_cf, &key_entry)
};
let u = if let Some(en) = db_res? {
if let Value::Int(u) = Tuple::new(en).get(0).unwrap() {
u
} else {
panic!("Unexpected value in storage id");
}
} else { 0 };
let mut new_data = Tuple::with_null_prefix();
new_data.push_int(u + 1);
if in_root {
self.txn.put(true, &self.perm_cf, key_entry, new_data)?;
} else {
self.txn.put(false, &self.temp_cf, key_entry, new_data)?;
}
Ok(u + 1)
}
fn get_stack_depth(&self) -> i32 {
pub fn get_stack_depth(&self) -> i32 {
self.stack_depth
}
@ -1030,19 +830,6 @@ impl<'s> Session<'s> {
Ok(())
}
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);
if in_root {
let data = self.txn.get(true, &self.perm_cf, key)?;
Ok(data.map(Tuple::new))
} else {
let data = self.txn.get(false, &self.temp_cf, key)?;
Ok(data.map(Tuple::new))
}
}
pub fn resolve(&self, name: &str) -> Result<Option<Tuple<SlicePtr>>> {
let mut tuple = Tuple::with_null_prefix();
tuple.push_str(name);
@ -1058,115 +845,6 @@ impl<'s> Session<'s> {
let res = self.txn.get(true, &self.perm_cf, root_key).map(|v| v.map(Tuple::new))?;
Ok(res)
}
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);
let mut assocs = vec![];
let it = self.txn.iterator(true, &self.perm_cf);
it.seek(&prefix);
for val in it.keys() {
let cur = Tuple::new(val);
if !cur.starts_with(&prefix) {
break;
}
let name = cur.get_text(4).ok_or_else(|| LogicError("Bad data".to_string()))?;
if let Some(data) = self.resolve(&name)? {
if data.data_kind()? == DataKind::Assoc {
assocs.push((name.to_string(), data));
}
}
}
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) {
break;
}
let name = cur.get_text(4).ok_or_else(|| LogicError("Bad data".to_string()))?;
if let Some(data) = self.resolve(&name)? {
if data.data_kind()? == DataKind::Assoc {
assocs.push((name.to_string(), data));
}
}
}
Ok(assocs)
}
pub fn delete_defined(&mut self, name: &str, in_root: bool) -> Result<()> {
let key = self.encode_definable_key(name, in_root);
if in_root {
self.txn.del(true, &self.perm_cf, key)?;
} else {
let it = self.txn.iterator(false, &self.temp_cf);
it.seek(&key);
if let Some(found_key) = it.key() {
let found_key_tuple = Tuple::new(found_key);
if found_key_tuple.starts_with(&key) {
let mut ikey = Tuple::with_null_prefix();
ikey.push_value(&found_key_tuple.get(1).unwrap());
ikey.push_value(&found_key_tuple.get(0).unwrap());
self.txn.del(false, &self.temp_cf, found_key_tuple)?;
self.txn.del(false, &self.temp_cf, ikey)?;
}
}
}
// TODO cleanup if the thing deleted is a table
Ok(())
}
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<bool> {
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(())
}
}

@ -0,0 +1,38 @@
// struct Filter;
//
// enum QueryPlan {
// Union {
// args: Vec<QueryPlan>
// },
// Intersection {
// args: Vec<QueryPlan>
// },
// Difference {
// left: Box<QueryPlan>,
// right: Box<QueryPlan>,
// },
// Selection {
// arg: Box<QueryPlan>,
// filter: (),
// },
// Projection {
// arg: Box<QueryPlan>,
// keys: (),
// fields: (),
// },
// Product {
// args: Vec<QueryPlan>
// },
// Join {
// args: Vec<QueryPlan>
// },
// LeftJoin {
// left: Box<QueryPlan>,
// right: Box<QueryPlan>
// },
// BaseRelation {
// relation: ()
// },
// }

@ -1,41 +1,3 @@
// struct Filter;
//
// enum QueryPlan {
// Union {
// args: Vec<QueryPlan>
// },
// Intersection {
// args: Vec<QueryPlan>
// },
// Difference {
// left: Box<QueryPlan>,
// right: Box<QueryPlan>,
// },
// Selection {
// arg: Box<QueryPlan>,
// filter: (),
// },
// Projection {
// arg: Box<QueryPlan>,
// keys: (),
// fields: (),
// },
// Product {
// args: Vec<QueryPlan>
// },
// Join {
// args: Vec<QueryPlan>
// },
// LeftJoin {
// left: Box<QueryPlan>,
// right: Box<QueryPlan>
// },
// BaseRelation {
// relation: ()
// },
// }
use std::collections::BTreeMap;
use pest::iterators::Pair;
use crate::db::engine::Session;

Loading…
Cancel
Save