start doing mutation

main
Ziyang Hu 2 years ago
parent 3a6fee6fe0
commit 832431c70f

@ -1,3 +1,4 @@
pub mod engine;
pub mod eval;
pub mod plan;
pub mod mutation;

@ -196,7 +196,7 @@ pub trait Environment<'t, T: AsRef<[u8]>> where Self: Sized {
let in_root = match pair.as_rule() {
Rule::global_def => true,
Rule::local_def => false,
_ => unreachable!()
r => panic!("Encountered definition with rule {:?}", r)
};
let (need_id, (name, mut tuple)) = self.parse_definition(

@ -0,0 +1,148 @@
use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet};
use pest::iterators::Pair;
use crate::db::engine::Session;
use crate::db::eval::Environment;
use crate::error::CozoError::LogicError;
use crate::error::Result;
use crate::parser::Rule;
use crate::parser::text_identifier::build_name_in_def;
use crate::relation::tuple::OwnTuple;
use crate::relation::value::Value;
impl<'a, 't> Session<'a, 't> {
pub fn run_mutation(&mut self, pair: Pair<Rule>) -> Result<()> {
let mut pairs = pair.into_inner();
let kind = pairs.next().unwrap();
let (evaluated, expr) = self.partial_eval(Value::from_pair(pairs.next().unwrap())?)?;
if !evaluated {
return Err(LogicError("Mutation encountered unevaluated expression".to_string()));
}
let expr = match expr {
Value::List(v) => v,
_ => return Err(LogicError("Mutation requires iterator of values".to_string()))
};
let mut default_kind = None;
let mut filters: Option<()> = None;
for p in pairs {
match p.as_rule() {
Rule::name_in_def => default_kind = Some(build_name_in_def(p, true)?),
Rule::mutation_filter => filters = Some(()), // TODO
_ => unreachable!()
}
}
println!("{:?}", kind);
println!("{:?}", expr);
println!("{:?}", default_kind);
println!("{:?}", filters);
let mut coercion_manager = TableCoercionManager::new(self, default_kind);
// Coercion
for item in expr {
let val_map = match item {
Value::Dict(d) => d,
_ => return Err(LogicError("Must be structs".to_string()))
};
coercion_manager.add(val_map)?;
// let explicit_tbl = val_map.get("_type");
// let tbl = match explicit_tbl {
// None => if let Some(v) = &default_kind {
// v as &str
// } else {
// return Err(LogicError("Cannot determine table kind".to_string()));
// }
// Some(v) => {
// match v {
// Value::Text(t) => t as &str,
// _ => return Err(LogicError("Cannot determine table kind".to_string()))
// }
// }
// };
// coercion_manager.coerce(tbl, val_map);
}
Ok(())
}
}
struct TableCoercionManager<'a, 'b, 't> {
sess: &'a Session<'b, 't>,
cache: BTreeMap<String, ()>,
categorized: BTreeMap<String, BTreeSet<OwnTuple>>,
default_tbl: Option<String>,
}
impl<'a, 'b, 't> TableCoercionManager<'a, 'b, 't> {
fn new(sess: &'a Session<'b, 't>, default_tbl: Option<String>) -> Self {
Self { sess, cache: BTreeMap::new(), categorized: BTreeMap::new(), default_tbl }
}
fn add(&mut self, val_map: BTreeMap<Cow<str>, Value>) -> Result<()> {
let tbl_name = match val_map.get("_type") {
Some(Value::Text(t)) => t as &str,
Some(_) => return Err(LogicError("Table kind must be text".to_string())),
None => match &self.default_tbl {
Some(v) => v as &str,
None => return Err(LogicError("Cannot determine table kind".to_string()))
}
};
match self.cache.get(tbl_name) {
None => {
self.cache.insert(tbl_name.to_string(), ());
}
Some(t) => {},
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::fs;
use pest::Parser as PestParser;
use crate::db::engine::Engine;
use crate::db::eval::Environment;
use crate::parser::{Parser, Rule};
#[test]
fn test_mutation() {
let db_path = "_test_db_mutation";
let engine = Engine::new(db_path.to_string(), true).unwrap();
{
let mut sess = engine.session().unwrap();
let s = r#"
create node "Person" {
*id: Int,
name: Text,
email: ?Text,
habits: ?[?Text]
}
create edge (Person)-[Friend]->(Person) {
relation: ?Text
}
"#;
for p in Parser::parse(Rule::file, s).unwrap() {
if p.as_rule() == Rule::EOI {
break;
}
sess.run_definition(p).unwrap();
}
sess.commit().unwrap();
}
{
let mut sess = engine.session().unwrap();
println!("{:#?}", sess.resolve("Person"));
let s = r#"
insert [{id: 1, name: "Jack"}, {id: 2, name: "Joe", habits: ["Balls"]}] as Person;
"#;
let p = Parser::parse(Rule::file, s).unwrap().next().unwrap();
sess.run_mutation(p);
}
drop(engine);
let _ = fs::remove_dir_all(db_path);
}
}

@ -1,4 +1,4 @@
file = _{SOI ~ statement* ~ EOI}
file = _{SOI ~ (statement | mutation)* ~ EOI}
// whitespace
@ -147,13 +147,13 @@ cols_def = { "{" ~ col_entry ~ ("," ~ col_entry)* ~ ","? ~ "}" }
col_list = {"(" ~ name_in_def ~ ("," ~ name_in_def)* ~ ","? ~ ")"}
node_def = { "node" ~ name_in_def ~ cols_def }
associate_def = { "assoc" ~ name_in_def ~ ":" ~ name_in_def ~ cols_def }
node_def = { "node" ~ name_in_def ~ cols_def ~ ";"?}
associate_def = { "assoc" ~ name_in_def ~ ":" ~ name_in_def ~ cols_def ~ ";"? }
edge_def = { "edge" ~
"(" ~ name_in_def ~ ")" ~ "-" ~ "[" ~ name_in_def ~ "]" ~ "->" ~ "(" ~ name_in_def ~ ")"
~ cols_def? }
index_def = { "index" ~ (name_in_def ~ ":")? ~ name_in_def ~ col_list }
type_def = { "type" ~ name_in_def ~ "=" ~ typing }
~ cols_def? ~ ";"? }
index_def = { "index" ~ (name_in_def ~ ":")? ~ name_in_def ~ col_list ~ ";"? }
type_def = { "type" ~ name_in_def ~ "=" ~ typing ~ ";"? }
definition = _{ node_def | associate_def | edge_def | type_def | index_def }
global_def = { "create" ~ definition }

Loading…
Cancel
Save