From bf448ea93574ddaaf41a092c4894a6e66c950664 Mon Sep 17 00:00:00 2001 From: Denis Smirnov <sd@picodata.io> Date: Fri, 17 Dec 2021 12:01:32 +0700 Subject: [PATCH] refactoring: move tree traversal to a separate module. --- src/ir.rs | 106 +------------------------------------------ src/ir/traversal.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 105 deletions(-) create mode 100644 src/ir/traversal.rs diff --git a/src/ir.rs b/src/ir.rs index 82ed8306d4..b092c3ea6c 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -6,6 +6,7 @@ pub mod distribution; pub mod expression; pub mod operator; pub mod relation; +pub mod traversal; pub mod value; use crate::errors::QueryPlannerError; @@ -14,7 +15,6 @@ use expression::Expression; use operator::Relational; use relation::Table; use serde::{Deserialize, Serialize}; -use std::cell::RefCell; use std::collections::{HashMap, HashSet}; /// Plan tree node. @@ -533,109 +533,5 @@ impl Plan { } } -/// Plan node iterator over its branches. -/// -/// For example, inner join returns at first a left child, then -/// the right one. But a relation scan doesn't have any children -/// and stop iteration at the moment. -/// -/// We need this iterator to traverse plan tree with `traversal` crate. -#[derive(Debug)] -pub struct BranchIterator<'n> { - node: &'n Node, - step: RefCell<usize>, - plan: &'n Plan, -} - -#[allow(dead_code)] -impl<'n> BranchIterator<'n> { - /// Constructor for a new branch iterator instance. - #[must_use] - pub fn new(node: &'n Node, plan: &'n Plan) -> Self { - BranchIterator { - node, - step: RefCell::new(0), - plan, - } - } -} - -impl<'n> Iterator for BranchIterator<'n> { - type Item = &'n Node; - - fn next(&mut self) -> Option<Self::Item> { - let get_next_child = |children: &Vec<usize>| -> Option<&Node> { - let current_step = *self.step.borrow(); - let child = children.get(current_step); - child.and_then(|pos| { - let node = self.plan.nodes.get(*pos); - *self.step.borrow_mut() += 1; - node - }) - }; - - match self.node { - Node::Expression(expr) => match expr { - Expression::Alias { child, .. } => { - let current_step = *self.step.borrow(); - if current_step == 0 { - *self.step.borrow_mut() += 1; - return self.plan.nodes.get(*child); - } - None - } - Expression::Bool { left, right, .. } => { - let current_step = *self.step.borrow(); - if current_step == 0 { - *self.step.borrow_mut() += 1; - return self.plan.nodes.get(*left); - } else if current_step == 1 { - *self.step.borrow_mut() += 1; - return self.plan.nodes.get(*right); - } - None - } - Expression::Constant { .. } | Expression::Reference { .. } => None, - Expression::Row { list, .. } => { - let current_step = *self.step.borrow(); - if let Some(node) = list.get(current_step) { - *self.step.borrow_mut() += 1; - return self.plan.nodes.get(*node); - } - None - } - }, - Node::Relational(rel) => match rel { - Relational::InnerJoin { - children, - condition, - .. - } => { - let current_step = *self.step.borrow(); - if current_step == 0 || current_step == 1 { - return get_next_child(children); - } else if current_step == 2 { - *self.step.borrow_mut() += 1; - return self.plan.nodes.get(*condition); - } - None - } - Relational::ScanRelation { .. } => None, - Relational::ScanSubQuery { children, .. } - | Relational::Motion { children, .. } - | Relational::Selection { children, .. } - | Relational::Projection { children, .. } => get_next_child(children), - Relational::UnionAll { children, .. } => { - let current_step = *self.step.borrow(); - if current_step == 0 || current_step == 1 { - return get_next_child(children); - } - None - } - }, - } - } -} - #[cfg(test)] mod tests; diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs new file mode 100644 index 0000000000..c201fba5ab --- /dev/null +++ b/src/ir/traversal.rs @@ -0,0 +1,108 @@ +use super::expression::Expression; +use super::operator::Relational; +use super::{Node, Plan}; +use std::cell::RefCell; + +/// Plan node iterator over its branches. +/// +/// For example, inner join returns at first a left child, then +/// the right one. But a relation scan doesn't have any children +/// and stop iteration at the moment. +/// +/// We need this iterator to traverse plan tree with `traversal` crate. +#[derive(Debug)] +pub struct BranchIterator<'n> { + node: &'n Node, + step: RefCell<usize>, + plan: &'n Plan, +} + +#[allow(dead_code)] +impl<'n> BranchIterator<'n> { + /// Constructor for a new branch iterator instance. + #[must_use] + pub fn new(node: &'n Node, plan: &'n Plan) -> Self { + BranchIterator { + node, + step: RefCell::new(0), + plan, + } + } +} + +impl<'n> Iterator for BranchIterator<'n> { + type Item = &'n Node; + + fn next(&mut self) -> Option<Self::Item> { + let get_next_child = |children: &Vec<usize>| -> Option<&Node> { + let current_step = *self.step.borrow(); + let child = children.get(current_step); + child.and_then(|pos| { + let node = self.plan.nodes.get(*pos); + *self.step.borrow_mut() += 1; + node + }) + }; + + match self.node { + Node::Expression(expr) => match expr { + Expression::Alias { child, .. } => { + let current_step = *self.step.borrow(); + if current_step == 0 { + *self.step.borrow_mut() += 1; + return self.plan.nodes.get(*child); + } + None + } + Expression::Bool { left, right, .. } => { + let current_step = *self.step.borrow(); + if current_step == 0 { + *self.step.borrow_mut() += 1; + return self.plan.nodes.get(*left); + } else if current_step == 1 { + *self.step.borrow_mut() += 1; + return self.plan.nodes.get(*right); + } + None + } + Expression::Constant { .. } | Expression::Reference { .. } => None, + Expression::Row { list, .. } => { + let current_step = *self.step.borrow(); + if let Some(node) = list.get(current_step) { + *self.step.borrow_mut() += 1; + return self.plan.nodes.get(*node); + } + None + } + }, + Node::Relational(rel) => match rel { + Relational::InnerJoin { + children, + condition, + .. + } => { + let current_step = *self.step.borrow(); + if current_step == 0 || current_step == 1 { + return get_next_child(children); + } else if current_step == 2 { + *self.step.borrow_mut() += 1; + return self.plan.nodes.get(*condition); + } + None + } + Relational::ScanRelation { .. } => None, + Relational::ScanSubQuery { children, .. } + | Relational::Motion { children, .. } + | Relational::Selection { children, .. } + | Relational::Projection { children, .. } => get_next_child(children), + Relational::UnionAll { children, .. } => { + let current_step = *self.step.borrow(); + if current_step == 0 || current_step == 1 { + return get_next_child(children); + } + None + } + }, + } + } +} -- GitLab