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> {
fn from(it: IteratorPtr<'a>) -> Self {
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)]
pub enum ExecPlan<'a> {
NodeItPlan {
it: IteratorSlot<'a>,
info: TableInfo,
binding: String,
binding: Option<String>,
},
EdgeItPlan {
it: IteratorSlot<'a>,
info: TableInfo,
binding: String,
binding: Option<String>,
},
EdgeKeyOnlyBwdItPlan {
it: IteratorSlot<'a>,
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: ..}
KeySortedWithAssocItPlan {
main: Box<ExecPlan<'a>>,
@ -144,6 +176,12 @@ impl<'a> ExecPlan<'a> {
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 }))
}
ExecPlan::EdgeKeyOnlyBwdItPlan { it, info } => {
ExecPlan::EdgeKeyOnlyBwdItPlan { it, info, .. } => {
let it = it.try_get()?;
let mut prefix_tuple = OwnTuple::with_prefix(info.table_id.id as u32);
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<_>>>()?;
Ok(Box::new(BagsUnionIterator { bags, current: 0 }))
}
ExecPlan::EdgeBwdItPlan { .. } => {
todo!()
}
ExecPlan::ChainJoinItPlan { .. } => {
todo!()
}
}
}
}
@ -1166,6 +1210,20 @@ mod tests {
let duration = start.elapsed();
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);
let _ = fs::remove_dir_all(db_path);

@ -1,7 +1,7 @@
use std::collections::btree_map::Entry;
use crate::db::engine::Session;
use crate::db::iterator::{ExecPlan, IteratorSlot, OutputItPlan};
use crate::db::query::{FromEl, Selection};
use crate::db::iterator::{ChainJoinKind, ExecPlan, IteratorSlot, OutputItPlan, TableRowGetter};
use crate::db::query::{EdgeOrNodeEl, EdgeOrNodeKind, FromEl, Selection};
use crate::db::table::{ColId, TableId, TableInfo};
use crate::error::Result;
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)> {
let res = match plan {
ExecPlan::NodeItPlan { info, binding, .. } => {
let amap = self.node_accessor_map(&binding, &info);
let amap = convert_to_relative_accessor_map(amap);
let amap = match &binding {
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 {
self.txn.iterator(true, &self.perm_cf)
} else {
@ -83,8 +88,13 @@ impl<'a> Session<'a> {
(plan, amap)
}
ExecPlan::EdgeItPlan { info, binding, .. } => {
let amap = self.edge_accessor_map(&binding, &info);
let amap = convert_to_relative_accessor_map(amap);
let amap = match &binding {
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 {
self.txn.iterator(true, &self.perm_cf)
} else {
@ -98,6 +108,9 @@ impl<'a> Session<'a> {
};
(plan, amap)
}
ExecPlan::EdgeBwdItPlan { .. } => {
todo!()
}
ExecPlan::EdgeKeyOnlyBwdItPlan { .. } => todo!(),
ExecPlan::KeySortedWithAssocItPlan { .. } => todo!(),
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 plan = ExecPlan::CartesianProdItPlan {
left: l_plan.into(),
right: r_plan.into()
right: r_plan.into(),
};
(plan, merge_accessor_map(l_map, r_map))
}
@ -141,6 +154,9 @@ impl<'a> Session<'a> {
(plan, amap)
}
ExecPlan::BagsUnionIt { .. } => todo!(),
ExecPlan::ChainJoinItPlan { .. } => {
todo!()
}
};
Ok(res)
}
@ -187,20 +203,70 @@ impl<'a> Session<'a> {
Ok(ExecPlan::NodeItPlan {
it: IteratorSlot::Dummy,
info: el.info,
binding: el.binding,
binding: Some(el.binding),
})
}
DataKind::Edge => {
Ok(ExecPlan::EdgeItPlan {
it: IteratorSlot::Dummy,
info: el.info,
binding: el.binding,
binding: Some(el.binding),
})
}
_ => 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 fst = from_data.next().ok_or_else(||
@ -210,7 +276,7 @@ impl<'a> Session<'a> {
let nxt = convert_el(nxt)?;
res = ExecPlan::CartesianProdItPlan {
left: res.into(),
right: nxt.into()
right: nxt.into(),
};
}
Ok(res)
@ -321,7 +387,7 @@ impl<'a> Session<'a> {
dst_key_typing: vec![],
associates: vec![],
},
binding: "".to_string(),
binding: None,
}
}
}

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

Loading…
Cancel
Save