From 31ca5bf79e63b161d615f792f84c98d5ec2fe6f9 Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Thu, 5 May 2022 19:20:43 +0800 Subject: [PATCH] field access conversion to tuple refs --- src/db/ddl.rs | 7 +++ src/db/env.rs | 27 ---------- src/db/eval.rs | 130 +++++++++++++++++++++--------------------------- src/db/plan.rs | 38 +++++++++----- src/db/table.rs | 24 +++++++++ 5 files changed, 112 insertions(+), 114 deletions(-) diff --git a/src/db/ddl.rs b/src/db/ddl.rs index 0da53d8e..5169e36d 100644 --- a/src/db/ddl.rs +++ b/src/db/ddl.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use pest::iterators::{Pair, Pairs}; use cozorocks::SlicePtr; use crate::db::engine::Session; +use crate::db::table::TableId; use crate::relation::tuple::{OwnTuple, Tuple}; use crate::relation::typing::Typing; use crate::parser::Rule; @@ -255,6 +256,12 @@ impl<'s> Session<'s> { } Ok(u + 1) } + pub fn make_table_id_valid(&self, tid: &mut TableId) -> Result<()> { + if !tid.is_valid() { + tid.id = self.get_next_storage_id(tid.in_root)?; + } + Ok(()) + } pub fn table_data(&self, id: i64, in_root: bool) -> Result>> { let mut key = Tuple::with_null_prefix(); diff --git a/src/db/env.rs b/src/db/env.rs index 038f8e21..af2adafa 100644 --- a/src/db/env.rs +++ b/src/db/env.rs @@ -16,33 +16,6 @@ use crate::relation::tuple::{OwnTuple, Tuple}; /// `[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); diff --git a/src/db/eval.rs b/src/db/eval.rs index 8542399d..f29241b2 100644 --- a/src/db/eval.rs +++ b/src/db/eval.rs @@ -1,15 +1,25 @@ use std::borrow::Cow; use std::collections::{BTreeMap}; +use cozorocks::SlicePtr; use crate::db::engine::{Session}; -use crate::db::env::TableEnv; +use crate::db::plan::AccessorMap; +use crate::db::table::{ColId, TableId}; use crate::relation::value::{Value}; use crate::error::{CozoError, Result}; use crate::error::CozoError::LogicError; +use crate::relation::tuple::{OwnTuple, Tuple}; use crate::relation::value; +pub fn extract_relevant_tables<'a>(value: Value<'a>) -> (Value<'a>, Vec<(TableId, ColId)>) { + todo!() +} + impl<'s> Session<'s> { + pub fn tuple_eval<'a>(&self, value: Value<'a>, tuples: Vec>) -> Result<(OwnTuple, OwnTuple)> { + todo!() + } pub fn partial_eval<'a>(&self, value: Value<'a>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { match value { v @ (Value::Null | Value::Bool(_) | @@ -56,7 +66,23 @@ impl<'s> Session<'s> { } } Value::FieldAccess(field, arg) => { - match *arg { + // convert to tuple refs + if let Value::Variable(v) = &*arg { + if let Some(sub_dict) = table_bindings.get(v.as_ref()) { + return match sub_dict.get(field.as_ref()) { + None => { + Err(LogicError("Cannot resolve field in bound table".to_string())) + } + Some(d) => { + Ok((false, Value::TupleRef(d.0, d.1))) + } + } + } + } + + // normal evaluation flow + let (_is_ev, arg) = self.partial_eval(*arg, params, table_bindings)?; + match arg { v @ (Value::Variable(_) | Value::IdxAccess(_, _) | Value::FieldAccess(_, _) | @@ -70,7 +96,8 @@ impl<'s> Session<'s> { } } Value::IdxAccess(idx, arg) => { - match *arg { + let (_is_ev, arg) = self.partial_eval(*arg, params, table_bindings)?; + match arg { v @ (Value::Variable(_) | Value::IdxAccess(_, _) | Value::FieldAccess(_, _) | @@ -87,6 +114,9 @@ impl<'s> Session<'s> { } } Value::Apply(op, args) => { + let args = args.into_iter() + .map(|v| self.partial_eval(v, params, table_bindings).map(|p| p.1)) + .collect::>>()?; Ok(match op.as_ref() { value::OP_STR_CAT => self.str_cat_values(args, params, table_bindings)?, value::OP_ADD => self.add_values(args, params, table_bindings)?, @@ -120,7 +150,7 @@ impl<'s> Session<'s> { } fn coalesce_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let res = args.into_iter().try_fold(vec![], |mut accum, cur| { match self.partial_eval(cur, params, table_bindings) { Ok((ev, cur)) => { @@ -151,7 +181,7 @@ impl<'s> Session<'s> { } } fn str_cat_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -167,7 +197,7 @@ impl<'s> Session<'s> { }) } fn add_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -186,7 +216,7 @@ impl<'s> Session<'s> { }) } fn sub_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -205,7 +235,7 @@ impl<'s> Session<'s> { }) } fn minus_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; if left == Value::Null { @@ -221,7 +251,7 @@ impl<'s> Session<'s> { }) } fn negate_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; if left == Value::Null { @@ -236,7 +266,7 @@ impl<'s> Session<'s> { }) } fn is_null_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; if left == Value::Null { @@ -248,7 +278,7 @@ impl<'s> Session<'s> { Ok((true, false.into())) } fn not_null_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; if left == Value::Null { @@ -260,7 +290,7 @@ impl<'s> Session<'s> { Ok((true, true.into())) } fn pow_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -279,7 +309,7 @@ impl<'s> Session<'s> { }) } fn gt_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -298,7 +328,7 @@ impl<'s> Session<'s> { }) } fn lt_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -317,7 +347,7 @@ impl<'s> Session<'s> { }) } fn ge_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -336,7 +366,7 @@ impl<'s> Session<'s> { }) } fn le_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -355,7 +385,7 @@ impl<'s> Session<'s> { }) } fn mod_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -371,7 +401,7 @@ impl<'s> Session<'s> { }) } fn mul_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -390,7 +420,7 @@ impl<'s> Session<'s> { }) } fn div_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -409,7 +439,7 @@ impl<'s> Session<'s> { }) } fn eq_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -422,7 +452,7 @@ impl<'s> Session<'s> { Ok((true, (left == right).into())) } fn ne_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut args = args.into_iter(); let (le, left) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; let (re, right) = self.partial_eval(args.next().unwrap(), params, table_bindings)?; @@ -435,7 +465,7 @@ impl<'s> Session<'s> { Ok((true, (left != right).into())) } fn or_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let res = args.into_iter().map(|v| self.partial_eval(v, params, table_bindings)) .try_fold( (true, false, vec![]), @@ -501,7 +531,7 @@ impl<'s> Session<'s> { } } fn concat_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut total_ret = vec![]; let mut cur_ret = vec![]; let mut evaluated = true; @@ -541,7 +571,7 @@ impl<'s> Session<'s> { } } fn merge_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let mut total_ret = vec![]; let mut cur_ret = BTreeMap::new(); let mut evaluated = true; @@ -581,7 +611,7 @@ impl<'s> Session<'s> { } } fn and_values<'a>(&self, args: Vec>, params: &BTreeMap>, - table_bindings: &TableEnv) -> Result<(bool, Value<'a>)> { + table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> { let res = args.into_iter().map(|v| self.partial_eval(v, params, table_bindings)) .try_fold( (true, false, vec![]), @@ -744,52 +774,4 @@ mod tests { drop(engine); fs::remove_dir_all(db_path).unwrap(); } - - #[test] - fn table_env() { - let mut tenv = TableEnv::default(); - tenv.current.insert("c".into(), ()); - let child = tenv.derive(); - let mut another = child.derive(); - another.current.insert("a".into(), ()); - println!("{:?}", another.resolve("c")); - println!("{:?}", another.resolve("a")); - println!("{:?}", another.resolve("d")); - } } - -// fn test_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { -// Ok(match exprs { -// [a] => { -// match self.visit_expr(a)? { -// Const(Null) => Const(Bool(true)), -// Const(_) => Const(Bool(false)), -// v => Value::Apply(Op::IsNull, vec![v]) -// } -// } -// _ => unreachable!() -// }) -// } -// -// fn not_null_expr<'a>(&self, exprs: &[Expr<'a>]) -> Result> { -// Ok(match exprs { -// [a] => { -// match self.visit_expr(a)? { -// Const(Null) => Const(Bool(false)), -// Const(_) => Const(Bool(true)), -// v => Value::Apply(Op::IsNull, vec![v]) -// } -// } -// _ => unreachable!() -// }) -// } -// #[cfg(test)] -// mod tests { -// use super::*; -// -// #[test] -// fn operators() { -// let ev = Evaluator::new(DummyStorage {}).unwrap(); -// -// } -// } \ No newline at end of file diff --git a/src/db/plan.rs b/src/db/plan.rs index 7a4652bf..d1fd74e8 100644 --- a/src/db/plan.rs +++ b/src/db/plan.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use pest::iterators::Pair; use crate::db::engine::Session; use crate::db::query::{FromEl, Selection}; -use crate::db::table::TableInfo; +use crate::db::table::{ColId, TableId, TableInfo}; use crate::relation::value::{StaticValue, Value}; use crate::parser::Rule; use crate::error::Result; @@ -48,9 +48,9 @@ pub enum QueryPlan { filter: StaticValue, }, BaseRelation { - // table: String, - // binding: String, - accessors: AccessorMap, + table: String, + binding: String, + // accessors: AccessorMap, info: TableInfo, }, } @@ -63,7 +63,7 @@ pub enum OuterJoinType { } -pub type AccessorMap = BTreeMap>; +pub type AccessorMap = BTreeMap>; impl<'a> Session<'a> { pub fn query_to_plan(&self, pair: Pair) -> Result<()> { @@ -88,8 +88,10 @@ impl<'a> Session<'a> { fn convert_from_data_to_plan(&self, mut from_data: Vec) -> Result { let res = match from_data.pop().unwrap() { FromEl::Simple(el) => { + println!("{:#?}", self.base_relation_to_accessor_map(&el.table, &el.binding, &el.info)); QueryPlan::BaseRelation { - accessors: self.single_table_accessor_map(el.binding, &el.info), + table: el.table, + binding: el.binding, info: el.info, } } @@ -97,13 +99,23 @@ impl<'a> Session<'a> { }; Ok(res) } - fn single_table_accessor_map(&self, binding: String, info: &TableInfo) -> AccessorMap { - // let mut ret = BTreeMap::new(); - // for (k, v) in &info.key_typing {} - // for (k, v) in &info.val_typing { - // - // } - todo!() + fn base_relation_to_accessor_map(&self, table: &str, binding: &str, info: &TableInfo) -> AccessorMap { + let mut ret = BTreeMap::new(); + for (i, (k, _)) in info.key_typing.iter().enumerate() { + ret.insert(k.into(), (info.table_id, (true, i).into())); + } + for (i, (k, _)) in info.val_typing.iter().enumerate() { + ret.insert(k.into(), (info.table_id, (false, i).into())); + } + for assoc in &info.associates { + for (i, (k, _)) in assoc.key_typing.iter().enumerate() { + ret.insert(k.into(), (assoc.table_id, (true, i).into())); + } + for (i, (k, _)) in assoc.val_typing.iter().enumerate() { + ret.insert(k.into(), (assoc.table_id, (false, i).into())); + } + } + BTreeMap::from([(binding.to_string(), ret)]) } fn convert_where_data_to_plan(&self, plan: QueryPlan, where_data: StaticValue) -> Result { let where_data = self.partial_eval(where_data, &Default::default(), &Default::default()); diff --git a/src/db/table.rs b/src/db/table.rs index eae516c3..92a1b15f 100644 --- a/src/db/table.rs +++ b/src/db/table.rs @@ -20,12 +20,36 @@ impl TableId { } } +impl From<(bool, usize)> for TableId { + fn from((in_root, id): (bool, usize)) -> Self { + Self { in_root, id: id as i64 } + } +} + +impl From<(bool, i64)> for TableId { + fn from((in_root, id): (bool, i64)) -> Self { + Self { in_root, id } + } +} + #[derive(Eq, PartialEq, Debug, Clone, Copy, Ord, PartialOrd)] pub struct ColId { pub is_key: bool, pub id: i64, } +impl From<(bool, i64)> for ColId { + fn from((is_key, id): (bool, i64)) -> Self { + Self { is_key, id } + } +} + +impl From<(bool, usize)> for ColId { + fn from((is_key, id): (bool, usize)) -> Self { + Self { is_key, id: id as i64 } + } +} + impl Default for TableId { fn default() -> Self { TableId { in_root: false, id: -1 }