Skip to content
Snippets Groups Projects
Commit 2a41644e authored by Denis Smirnov's avatar Denis Smirnov
Browse files

feat: implement relational node traversal iterator

Now we can traverse only relational nodes in the tree in arbitrary
order.
parent 15a4e628
No related branches found
No related tags found
1 merge request!1414sbroad import
use super::expression::Expression;
use super::operator::Bool;
use super::operator::{Bool, Relational};
use super::{Node, Nodes};
use std::cell::RefCell;
/// Relational node's child iterator.
///
/// Iterator returns next relational node in the plan tree.
#[derive(Debug)]
pub struct RelationalIterator<'n> {
current: &'n usize,
child: RefCell<usize>,
nodes: &'n Nodes,
}
/// Expression node's children iterator.
///
/// Iterator returns the next child for expression
......@@ -43,6 +53,15 @@ impl<'n> Nodes {
nodes: self,
}
}
#[must_use]
pub fn rel_iter(&'n self, current: &'n usize) -> RelationalIterator<'n> {
RelationalIterator {
current,
child: RefCell::new(0),
nodes: self,
}
}
}
impl<'n> Iterator for ExpressionIterator<'n> {
......@@ -114,5 +133,31 @@ impl<'n> Iterator for EqClassIterator<'n> {
}
}
impl<'n> Iterator for RelationalIterator<'n> {
type Item = &'n usize;
fn next(&mut self) -> Option<Self::Item> {
match self.nodes.arena.get(*self.current) {
Some(Node::Relational(
Relational::InnerJoin { children, .. }
| Relational::Motion { children, .. }
| Relational::Projection { children, .. }
| Relational::ScanSubQuery { children, .. }
| Relational::Selection { children, .. }
| Relational::UnionAll { children, .. },
)) => {
let step = *self.child.borrow();
if step < children.len() {
*self.child.borrow_mut() += 1;
return children.get(step);
}
None
}
Some(Node::Relational(Relational::ScanRelation { .. }) | Node::Expression(_))
| None => None,
}
}
}
#[cfg(test)]
mod tests;
use crate::ir::operator::*;
use crate::ir::relation::*;
use crate::ir::value::*;
use crate::ir::*;
use pretty_assertions::assert_eq;
use traversal::{Bft, DftPre};
use traversal::{Bft, DftPost, DftPre};
#[test]
fn expression_bft() {
......@@ -40,7 +41,7 @@ fn expression_bft() {
}
#[test]
fn and_chain() {
fn and_chain_pre() {
// (((b1 or b2) and b3) and b4) and (b5 = (b6 = b7))
let mut plan = Plan::new();
......@@ -73,3 +74,38 @@ fn and_chain() {
assert_eq!(dft_pre.next(), Some((3, &b7)));
assert_eq!(dft_pre.next(), None);
}
#[test]
fn relational_post() {
// select * from t1 union all (select * from t2 where a = 1)
// output: scan t1, scan t2, selection, union all
// Initialize plan
let mut plan = Plan::new();
let t1 = Table::new_seg("t1", vec![Column::new("a", Type::Boolean)], &["a"]).unwrap();
plan.add_rel(t1);
let scan_t1_id = plan.add_scan("t1").unwrap();
let t2 = Table::new_seg("t2", vec![Column::new("a", Type::Boolean)], &["a"]).unwrap();
plan.add_rel(t2);
let scan_t2_id = plan.add_scan("t2").unwrap();
let id = plan.nodes.next_id();
let a = plan.add_row_from_child(id, scan_t2_id, &["a"]).unwrap();
let const1 = plan.add_const(Value::number_from_str("1").unwrap());
let eq = plan.nodes.add_bool(a, Bool::Eq, const1).unwrap();
let selection_id = plan.add_select(scan_t2_id, eq, id).unwrap();
let union_id = plan.add_union_all(scan_t1_id, selection_id).unwrap();
plan.set_top(union_id).unwrap();
let top = plan.top.unwrap();
// Traverse the tree
let mut dft_post = DftPost::new(&top, |node| plan.nodes.rel_iter(node));
assert_eq!(dft_post.next(), Some((1, &scan_t1_id)));
assert_eq!(dft_post.next(), Some((2, &scan_t2_id)));
assert_eq!(dft_post.next(), Some((1, &selection_id)));
assert_eq!(dft_post.next(), Some((0, &union_id)));
assert_eq!(dft_post.next(), None);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment