start chain join

main
Ziyang Hu 2 years ago
parent 75863ddae8
commit 95af831c82

@ -25,6 +25,16 @@ impl<'a> Debug for IteratorSlot<'a> {
} }
} }
pub enum TableRowGetter {
Dummy,
}
impl Debug for TableRowGetter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self { TableRowGetter::Dummy => write!(f, "DummyRowGetter") }
}
}
impl<'a> From<IteratorPtr<'a>> for IteratorSlot<'a> { impl<'a> From<IteratorPtr<'a>> for IteratorSlot<'a> {
fn from(it: IteratorPtr<'a>) -> Self { fn from(it: IteratorPtr<'a>) -> Self {
Self::Reified(it) Self::Reified(it)
@ -40,23 +50,45 @@ impl<'a> IteratorSlot<'a> {
} }
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ChainJoinKind {
NodeToFwdEdge,
NodeToBwdEdge,
FwdEdgeToNode,
BwdEdgeToNode
}
#[derive(Debug)] #[derive(Debug)]
pub enum ExecPlan<'a> { pub enum ExecPlan<'a> {
NodeItPlan { NodeItPlan {
it: IteratorSlot<'a>, it: IteratorSlot<'a>,
info: TableInfo, info: TableInfo,
binding: String, binding: Option<String>,
}, },
EdgeItPlan { EdgeItPlan {
it: IteratorSlot<'a>, it: IteratorSlot<'a>,
info: TableInfo, info: TableInfo,
binding: String, binding: Option<String>,
}, },
EdgeKeyOnlyBwdItPlan { EdgeKeyOnlyBwdItPlan {
it: IteratorSlot<'a>, it: IteratorSlot<'a>,
info: TableInfo, info: TableInfo,
binding: Option<String>,
},
EdgeBwdItPlan {
it: IteratorSlot<'a>,
info: TableInfo,
binding: Option<String>,
getter: TableRowGetter,
},
ChainJoinItPlan {
left: Box<ExecPlan<'a>>,
right: TableRowGetter,
right_info: TableInfo,
kind: ChainJoinKind,
left_outer: bool,
right_outer: bool
}, },
// EdgeBwdIt { it: IteratorPtr<'a>, sess: &'a Session<'a>, tid: u32 },
// IndexIt {it: ..} // IndexIt {it: ..}
KeySortedWithAssocItPlan { KeySortedWithAssocItPlan {
main: Box<ExecPlan<'a>>, main: Box<ExecPlan<'a>>,
@ -144,6 +176,12 @@ impl<'a> ExecPlan<'a> {
bags.get(0).unwrap().tuple_widths() bags.get(0).unwrap().tuple_widths()
} }
} }
ExecPlan::EdgeBwdItPlan { .. } => {
todo!()
}
ExecPlan::ChainJoinItPlan { .. } => {
todo!()
}
} }
} }
} }
@ -181,7 +219,7 @@ impl<'a> ExecPlan<'a> {
Ok(Box::new(EdgeIterator { it, started: false, src_table_id: info.src_table_id.id })) Ok(Box::new(EdgeIterator { it, started: false, src_table_id: info.src_table_id.id }))
} }
ExecPlan::EdgeKeyOnlyBwdItPlan { it, info } => { ExecPlan::EdgeKeyOnlyBwdItPlan { it, info, .. } => {
let it = it.try_get()?; let it = it.try_get()?;
let mut prefix_tuple = OwnTuple::with_prefix(info.table_id.id as u32); let mut prefix_tuple = OwnTuple::with_prefix(info.table_id.id as u32);
prefix_tuple.push_int(info.dst_table_id.id); prefix_tuple.push_int(info.dst_table_id.id);
@ -275,6 +313,12 @@ impl<'a> ExecPlan<'a> {
let bags = bags.iter().map(|i| i.iter()).collect::<Result<Vec<_>>>()?; let bags = bags.iter().map(|i| i.iter()).collect::<Result<Vec<_>>>()?;
Ok(Box::new(BagsUnionIterator { bags, current: 0 })) Ok(Box::new(BagsUnionIterator { bags, current: 0 }))
} }
ExecPlan::EdgeBwdItPlan { .. } => {
todo!()
}
ExecPlan::ChainJoinItPlan { .. } => {
todo!()
}
} }
} }
} }
@ -1166,6 +1210,20 @@ mod tests {
let duration = start.elapsed(); let duration = start.elapsed();
println!("Time elapsed {:?}", duration); println!("Time elapsed {:?}", duration);
let s = r##"from (e:Employee)-[hj:HasJob]->(j:Job)
where e.id == 110
select { fname: e.first_name, salary: hj.salary, job: j.title }"##;
let parsed = Parser::parse(Rule::relational_query, s)?.next().unwrap();
let plan = sess.query_to_plan(parsed)?;
println!("{:?}", plan);
let plan = sess.reify_output_plan(plan)?;
println!("{:?}", plan);
for val in plan.iter()? {
println!("{}", val?)
}
} }
drop(engine); drop(engine);
let _ = fs::remove_dir_all(db_path); let _ = fs::remove_dir_all(db_path);

@ -1,7 +1,7 @@
use std::collections::btree_map::Entry; use std::collections::btree_map::Entry;
use crate::db::engine::Session; use crate::db::engine::Session;
use crate::db::iterator::{ExecPlan, IteratorSlot, OutputItPlan}; use crate::db::iterator::{ChainJoinKind, ExecPlan, IteratorSlot, OutputItPlan, TableRowGetter};
use crate::db::query::{FromEl, Selection}; use crate::db::query::{EdgeOrNodeEl, EdgeOrNodeKind, FromEl, Selection};
use crate::db::table::{ColId, TableId, TableInfo}; use crate::db::table::{ColId, TableId, TableInfo};
use crate::error::Result; use crate::error::Result;
use crate::parser::Rule; use crate::parser::Rule;
@ -67,8 +67,13 @@ impl<'a> Session<'a> {
fn do_reify_intermediate_plan(&'a self, plan: ExecPlan<'a>) -> Result<(ExecPlan<'a>, AccessorMap)> { fn do_reify_intermediate_plan(&'a self, plan: ExecPlan<'a>) -> Result<(ExecPlan<'a>, AccessorMap)> {
let res = match plan { let res = match plan {
ExecPlan::NodeItPlan { info, binding, .. } => { ExecPlan::NodeItPlan { info, binding, .. } => {
let amap = self.node_accessor_map(&binding, &info); let amap = match &binding {
let amap = convert_to_relative_accessor_map(amap); None => Default::default(),
Some(binding) => {
let amap = self.node_accessor_map(binding, &info);
convert_to_relative_accessor_map(amap)
}
};
let it = if info.table_id.in_root { let it = if info.table_id.in_root {
self.txn.iterator(true, &self.perm_cf) self.txn.iterator(true, &self.perm_cf)
} else { } else {
@ -83,8 +88,13 @@ impl<'a> Session<'a> {
(plan, amap) (plan, amap)
} }
ExecPlan::EdgeItPlan { info, binding, .. } => { ExecPlan::EdgeItPlan { info, binding, .. } => {
let amap = self.edge_accessor_map(&binding, &info); let amap = match &binding {
let amap = convert_to_relative_accessor_map(amap); None => Default::default(),
Some(binding) => {
let amap = self.edge_accessor_map(&binding, &info);
convert_to_relative_accessor_map(amap)
}
};
let it = if info.table_id.in_root { let it = if info.table_id.in_root {
self.txn.iterator(true, &self.perm_cf) self.txn.iterator(true, &self.perm_cf)
} else { } else {
@ -98,6 +108,9 @@ impl<'a> Session<'a> {
}; };
(plan, amap) (plan, amap)
} }
ExecPlan::EdgeBwdItPlan { .. } => {
todo!()
}
ExecPlan::EdgeKeyOnlyBwdItPlan { .. } => todo!(), ExecPlan::EdgeKeyOnlyBwdItPlan { .. } => todo!(),
ExecPlan::KeySortedWithAssocItPlan { .. } => todo!(), ExecPlan::KeySortedWithAssocItPlan { .. } => todo!(),
ExecPlan::CartesianProdItPlan { left, right } => { ExecPlan::CartesianProdItPlan { left, right } => {
@ -106,7 +119,7 @@ impl<'a> Session<'a> {
let r_map = shift_accessor_map(r_map, l_plan.tuple_widths()); let r_map = shift_accessor_map(r_map, l_plan.tuple_widths());
let plan = ExecPlan::CartesianProdItPlan { let plan = ExecPlan::CartesianProdItPlan {
left: l_plan.into(), left: l_plan.into(),
right: r_plan.into() right: r_plan.into(),
}; };
(plan, merge_accessor_map(l_map, r_map)) (plan, merge_accessor_map(l_map, r_map))
} }
@ -141,6 +154,9 @@ impl<'a> Session<'a> {
(plan, amap) (plan, amap)
} }
ExecPlan::BagsUnionIt { .. } => todo!(), ExecPlan::BagsUnionIt { .. } => todo!(),
ExecPlan::ChainJoinItPlan { .. } => {
todo!()
}
}; };
Ok(res) Ok(res)
} }
@ -187,20 +203,70 @@ impl<'a> Session<'a> {
Ok(ExecPlan::NodeItPlan { Ok(ExecPlan::NodeItPlan {
it: IteratorSlot::Dummy, it: IteratorSlot::Dummy,
info: el.info, info: el.info,
binding: el.binding, binding: Some(el.binding),
}) })
} }
DataKind::Edge => { DataKind::Edge => {
Ok(ExecPlan::EdgeItPlan { Ok(ExecPlan::EdgeItPlan {
it: IteratorSlot::Dummy, it: IteratorSlot::Dummy,
info: el.info, info: el.info,
binding: el.binding, binding: Some(el.binding),
}) })
} }
_ => Err(LogicError("Wrong type for table binding".to_string())) _ => Err(LogicError("Wrong type for table binding".to_string()))
} }
} }
FromEl::Chain(_) => todo!(), FromEl::Chain(ch) => {
let mut it = ch.into_iter();
let nxt = it.next().ok_or_else(|| LogicError("Empty chain not allowed".to_string()))?;
let mut prev_kind = nxt.kind;
let mut prev_left_outer = nxt.left_outer_marker;
let mut plan = match prev_kind {
EdgeOrNodeKind::Node => {
ExecPlan::NodeItPlan {
it: IteratorSlot::Dummy,
info: nxt.info,
binding: nxt.binding,
}
}
EdgeOrNodeKind::FwdEdge => {
ExecPlan::EdgeItPlan {
it: IteratorSlot::Dummy,
info: nxt.info,
binding: nxt.binding,
}
}
EdgeOrNodeKind::BwdEdge => {
ExecPlan::EdgeBwdItPlan {
it: IteratorSlot::Dummy,
info: nxt.info,
binding: nxt.binding,
getter: TableRowGetter::Dummy
}
}
};
for el in it {
plan = ExecPlan::ChainJoinItPlan {
left: plan.into(),
right: TableRowGetter::Dummy,
right_info: el.info,
kind: match (prev_kind, el.kind) {
(EdgeOrNodeKind::Node, EdgeOrNodeKind::FwdEdge) => ChainJoinKind::NodeToFwdEdge,
(EdgeOrNodeKind::Node, EdgeOrNodeKind::BwdEdge) => ChainJoinKind::NodeToBwdEdge,
(EdgeOrNodeKind::FwdEdge, EdgeOrNodeKind::Node) => ChainJoinKind::FwdEdgeToNode,
(EdgeOrNodeKind::BwdEdge, EdgeOrNodeKind::Node) => ChainJoinKind::BwdEdgeToNode,
_ => unreachable!()
},
left_outer: prev_left_outer,
right_outer: el.right_outer_marker
};
prev_kind = el.kind;
prev_left_outer = el.left_outer_marker;
}
println!("{:#?}", plan);
Ok(plan)
}
}; };
let mut from_data = from_data.into_iter(); let mut from_data = from_data.into_iter();
let fst = from_data.next().ok_or_else(|| let fst = from_data.next().ok_or_else(||
@ -210,7 +276,7 @@ impl<'a> Session<'a> {
let nxt = convert_el(nxt)?; let nxt = convert_el(nxt)?;
res = ExecPlan::CartesianProdItPlan { res = ExecPlan::CartesianProdItPlan {
left: res.into(), left: res.into(),
right: nxt.into() right: nxt.into(),
}; };
} }
Ok(res) Ok(res)
@ -321,7 +387,7 @@ impl<'a> Session<'a> {
dst_key_typing: vec![], dst_key_typing: vec![],
associates: vec![], associates: vec![],
}, },
binding: "".to_string(), binding: None,
} }
} }
} }

@ -22,7 +22,7 @@ pub struct SimpleFromEl {
pub info: TableInfo, pub info: TableInfo,
} }
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum EdgeOrNodeKind { pub enum EdgeOrNodeKind {
FwdEdge, FwdEdge,
BwdEdge, BwdEdge,

Loading…
Cancel
Save