fix value eval problem

main
Ziyang Hu 2 years ago
parent 2f68fe3919
commit cd664ce270

@ -188,7 +188,7 @@ impl<'s> Session<'s> {
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)),
DataKind::Data | DataKind::Val | DataKind::Type => return Err(CozoError::UnexpectedDataKind(kind)),
_ => {}
};
let is_global = src_tbl.get_bool(0).expect("Data corrupt");

@ -17,7 +17,7 @@ use crate::relation::tuple::{OwnTuple, Tuple};
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);
let mut data = Tuple::with_data_prefix(DataKind::Val);
data.push_value(val);
self.define_data(name, data, in_root)
}
@ -74,7 +74,7 @@ impl<'s> Session<'s> {
None => Ok(None),
Some(t) => {
match t.data_kind()? {
DataKind::Value => Ok(Some(t.get(0)
DataKind::Val => Ok(Some(t.get(0)
.ok_or_else(|| CozoError::LogicError("Corrupt".to_string()))?
.to_static())),
k => Err(CozoError::UnexpectedDataKind(k))

@ -134,10 +134,23 @@ impl<'a> Session<'a> {
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use std::fs;
use crate::db::engine::Engine;
use crate::parser::{Parser, Rule};
use pest::Parser as PestParser;
use crate::db::query::FromEl;
use crate::relation::value::Value;
use crate::error::Result;
#[test]
fn pair_value() -> Result<()> {
let s = "{x: e.first_name ++ ' ' ++ e.last_name, y: [e.a, e.b ++ e.c]}";
let res = Parser::parse(Rule::expr, s).unwrap().next().unwrap();
let v = Value::from_pair(res)?;
println!("{:#?}", v);
Ok(())
}
#[test]
fn plan() {
@ -145,31 +158,9 @@ mod tests {
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
}
create node Z {
*id: Text
}
let s = fs::read_to_string("test_data/hr.cozo").unwrap();
create assoc WorkInfo : Person {
work_id: Int
}
create assoc RelationshipData: Person {
status: Text
}
"#;
for p in Parser::parse(Rule::file, s).unwrap() {
for p in Parser::parse(Rule::file, &s).unwrap() {
if p.as_rule() == Rule::EOI {
break;
}
@ -177,9 +168,37 @@ mod tests {
}
sess.commit().unwrap();
let s = r#"from p:Person select p {id, name}"#;
let parsed = Parser::parse(Rule::relational_query, s).unwrap().next().unwrap();
let _plan = sess.query_to_plan(parsed).unwrap();
let data = fs::read_to_string("test_data/hr.json").unwrap();
let value = Value::parse_str(&data).unwrap();
let s = "insert $data;";
let p = Parser::parse(Rule::file, &s).unwrap().next().unwrap();
let params = BTreeMap::from([("$data".into(), value)]);
assert!(sess.run_mutation(p.clone(), &params).is_ok());
sess.commit().unwrap();
let s = "from e:Employee";
let p = Parser::parse(Rule::from_pattern, s).unwrap().next().unwrap();
let from_pat = match sess.parse_from_pattern(p).unwrap().pop().unwrap() {
FromEl::Simple(s) => s,
FromEl::Chain(_) => panic!()
};
let s = "select {id: e.id, data: e.first_name ++ ' ' ++ e.last_name}";
let p = Parser::parse(Rule::select_pattern, s).unwrap().next().unwrap();
println!("{:#?}", p);
let sel_pat = sess.parse_select_pattern(p).unwrap();
println!("{:?}", sel_pat);
let amap = sess.base_relation_to_accessor_map(&from_pat.table, &from_pat.binding, &from_pat.info);
println!("VALS ORIGINAL {:?}", sel_pat.vals);
let (_, vals) = sess.partial_eval(sel_pat.vals,& Default::default(), &amap).unwrap();
println!("VALS AFTER 1 {:?}", vals);
let (vals, rel_tbls) = vals.extract_relevant_tables().unwrap();
println!("VALS AFTER 2 {:?}", vals);
println!("{:?}", from_pat);
println!("{:?}", amap);
println!("{:?}", rel_tbls);
}
drop(engine);
let _ = fs::remove_dir_all(db_path);

@ -2,13 +2,12 @@ use std::collections::BTreeMap;
use pest::iterators::Pair;
use crate::db::engine::Session;
use crate::db::table::TableInfo;
use crate::error::CozoError::LogicError;
use crate::parser::Rule;
use crate::error::{CozoError, Result};
use crate::parser::text_identifier::{build_name_in_def, parse_string};
use crate::relation::data::DataKind;
use crate::relation::value;
use crate::relation::value::{build_expr_primary, METHOD_MERGE, StaticValue, Value};
use crate::relation::value::{StaticValue, Value};
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum FromEl {
@ -56,7 +55,7 @@ impl<'a> Session<'a> {
let mut pairs = pair.into_inner();
let name = pairs.next().unwrap().as_str();
if name.starts_with('_') {
return Err(LogicError("Pattern binding cannot start with underscore".to_string()));
return Err(CozoError::LogicError("Pattern binding cannot start with underscore".to_string()));
}
let table_name = build_name_in_def(pairs.next().unwrap(), true)?;
let table_info = self.get_table_info(&table_name)?;
@ -117,13 +116,16 @@ impl<'a> Session<'a> {
if !connects {
return Err(CozoError::LogicError("Chain does not connect".to_string()));
}
if res.is_empty() {
return Err(CozoError::LogicError("Empty chain not allowed".to_string()));
}
Ok(FromEl::Chain(res))
}
fn parse_node_pattern(&self, pair: Pair<Rule>) -> Result<EdgeOrNodeEl> {
let (table, binding, info) = self.parse_node_or_edge(pair)?;
if info.kind != DataKind::Node {
return Err(LogicError(format!("{} is not a node", table)));
return Err(CozoError::LogicError(format!("{} is not a node", table)));
}
Ok(EdgeOrNodeEl {
table,
@ -138,7 +140,7 @@ impl<'a> Session<'a> {
fn parse_edge_pattern(&self, pair: Pair<Rule>, is_fwd: bool) -> Result<EdgeOrNodeEl> {
let (table, binding, info) = self.parse_node_or_edge(pair)?;
if info.kind != DataKind::Edge {
return Err(LogicError(format!("{} is not an edge", table)));
return Err(CozoError::LogicError(format!("{} is not an edge", table)));
}
Ok(EdgeOrNodeEl {
table,
@ -201,12 +203,14 @@ impl<'a> Session<'a> {
Rule::dict_pair => {
let mut inner = p.into_inner();
let name = parse_string(inner.next().unwrap())?;
let val = build_expr_primary(inner.next().unwrap())?;
let val_pair = inner.next().unwrap();
println!("{:?}", val_pair);
let val = Value::from_pair(val_pair)?;
collected_vals.insert(name.into(), val);
}
Rule::spreading => {
let el = p.into_inner().next().unwrap();
let to_concat = build_expr_primary(el)?;
let to_concat = Value::from_pair(el)?;
if !matches!(to_concat, Value::Dict(_) | Value::Variable(_) |
Value::IdxAccess(_, _) | Value:: FieldAccess(_, _) | Value::Apply(_, _)) {
return Err(CozoError::LogicError("Cannot spread".to_string()));
@ -233,7 +237,7 @@ impl<'a> Session<'a> {
if !collected_vals.is_empty() {
merged.push(Value::Dict(collected_vals));
}
Value::Apply(METHOD_MERGE.into(), merged).to_static()
Value::Apply(value::METHOD_MERGE.into(), merged).to_static()
};
let mut ordering = vec![];

@ -11,7 +11,7 @@ pub enum DataKind {
Edge = 2,
Assoc = 3,
Index = 4,
Value = 5,
Val = 5,
Type = 6,
}
// In storage, key layout is `[0, name, stack_depth]` where stack_depth is a non-positive number as zigzag
@ -27,7 +27,7 @@ impl<T: AsRef<[u8]>> Tuple<T> {
2 => Edge,
3 => Assoc,
4 => Index,
5 => Value,
5 => Val,
6 => Type,
v => return Err(CozoError::UndefinedDataKind(v))
})

@ -176,8 +176,13 @@ impl<'a> Value<'a> {
Value::from_pair(pair)
}
pub fn extract_relevant_tables(self) -> Result<(Self, Vec<TableId>)> {
let mut coll = vec![];
let res = self.do_extract_relevant_tables(&mut coll)?;
Ok((res, coll))
}
pub fn extract_relevant_tables(self, coll: &mut Vec<TableId>) -> Result<Self> {
fn do_extract_relevant_tables(self, coll: &mut Vec<TableId>) -> Result<Self> {
Ok(match self {
v @ (Value::Null |
Value::Bool(_) |
@ -188,13 +193,13 @@ impl<'a> Value<'a> {
Value::Variable(_)) => v,
Value::List(l) => {
Value::List(l.into_iter()
.map(|v| v.extract_relevant_tables(coll))
.map(|v| v.do_extract_relevant_tables(coll))
.collect::<Result<Vec<_>>>()?)
}
Value::Dict(d) => {
Value::Dict(d.into_iter()
.map(|(k, v)|
v.extract_relevant_tables(coll).map(|v| (k, v)))
v.do_extract_relevant_tables(coll).map(|v| (k, v)))
.collect::<Result<BTreeMap<_, _>>>()?)
}
Value::TupleRef(tid, cid) => {
@ -207,14 +212,14 @@ impl<'a> Value<'a> {
}
Value::Apply(op, args) => {
Value::Apply(op, args.into_iter()
.map(|v| v.extract_relevant_tables(coll))
.map(|v| v.do_extract_relevant_tables(coll))
.collect::<Result<Vec<_>>>()?)
}
Value::FieldAccess(field, arg) => {
Value::FieldAccess(field, arg.extract_relevant_tables(coll)?.into())
Value::FieldAccess(field, arg.do_extract_relevant_tables(coll)?.into())
}
Value::IdxAccess(idx, arg) => {
Value::IdxAccess(idx, arg.extract_relevant_tables(coll)?.into())
Value::IdxAccess(idx, arg.do_extract_relevant_tables(coll)?.into())
}
Value::EndSentinel => {
return Err(LogicError("Encountered end sentinel".to_string()));
@ -445,7 +450,7 @@ fn build_expr_infix<'a>(lhs: Result<Value<'a>>, op: Pair<Rule>, rhs: Result<Valu
}
pub fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
match pair.as_rule() {
Rule::expr => build_expr_primary(pair.into_inner().next().unwrap()),
Rule::term => {
@ -466,7 +471,7 @@ pub fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
let mut pairs = p.into_inner();
let method_name = pairs.next().unwrap().as_str();
let mut args = vec![head];
args.extend(pairs.map(build_expr_primary).collect::<Result<Vec<_>>>()?);
args.extend(pairs.map(Value::from_pair).collect::<Result<Vec<_>>>()?);
head = Value::Apply(method_name.into(), args);
}
_ => todo!()
@ -502,10 +507,10 @@ pub fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
let mut collected = vec![];
for p in pair.into_inner() {
match p.as_rule() {
Rule::expr => collected.push(build_expr_primary(p)?),
Rule::expr => collected.push(Value::from_pair(p)?),
Rule::spreading => {
let el = p.into_inner().next().unwrap();
let to_concat = build_expr_primary(el)?;
let to_concat = Value::from_pair(el)?;
if !matches!(to_concat, Value::List(_) | Value::Variable(_) |
Value::IdxAccess(_, _) | Value:: FieldAccess(_, _) | Value::Apply(_, _)) {
return Err(CozoError::LogicError("Cannot spread".to_string()));
@ -535,7 +540,7 @@ pub fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
Rule::dict_pair => {
let mut inner = p.into_inner();
let name = parse_string(inner.next().unwrap())?;
let val = build_expr_primary(inner.next().unwrap())?;
let val = Value::from_pair(inner.next().unwrap())?;
collected.insert(name.into(), val);
}
Rule::scoped_accessor => {

Loading…
Cancel
Save