diff --git a/sbroad-core/src/ir/tree.rs b/sbroad-core/src/ir/tree.rs
index d2ffd50990a59a84f501245e4eff18b73c77a2ee..f301a2a99dbd6230bcb279c23e1e2eb1d95dd10f 100644
--- a/sbroad-core/src/ir/tree.rs
+++ b/sbroad-core/src/ir/tree.rs
@@ -1,12 +1,114 @@
 //! IR tree traversal module.
 
 use super::{Nodes, Plan};
+use crate::ir::expression::Expression;
 use std::cell::RefCell;
 
 trait TreeIterator<'nodes> {
     fn get_current(&self) -> usize;
     fn get_child(&self) -> &RefCell<usize>;
     fn get_nodes(&self) -> &'nodes Nodes;
+
+    fn handle_trim(&mut self, expr: &'nodes Expression) -> Option<&'nodes usize> {
+        let Expression::Trim {
+            pattern, target, ..
+        } = expr
+        else {
+            panic!("Trim expected")
+        };
+        let child_step = *self.get_child().borrow();
+        match child_step {
+            0 => {
+                *self.get_child().borrow_mut() += 1;
+                match pattern {
+                    Some(_) => pattern.as_ref(),
+                    None => Some(target),
+                }
+            }
+            1 => {
+                *self.get_child().borrow_mut() += 1;
+                match pattern {
+                    Some(_) => Some(target),
+                    None => None,
+                }
+            }
+            _ => None,
+        }
+    }
+
+    fn handle_left_right_children(&mut self, expr: &'nodes Expression) -> Option<&'nodes usize> {
+        let (Expression::Bool { left, right, .. }
+        | Expression::Arithmetic { left, right, .. }
+        | Expression::Concat { left, right, .. }) = expr
+        else {
+            panic!("Expected expression with left and right children")
+        };
+        let child_step = *self.get_child().borrow();
+        if child_step == 0 {
+            *self.get_child().borrow_mut() += 1;
+            return Some(left);
+        } else if child_step == 1 {
+            *self.get_child().borrow_mut() += 1;
+            return Some(right);
+        }
+        None
+    }
+
+    fn handle_single_child(&mut self, expr: &'nodes Expression) -> Option<&'nodes usize> {
+        let (Expression::Alias { child, .. }
+        | Expression::ExprInParentheses { child }
+        | Expression::Cast { child, .. }
+        | Expression::Unary { child, .. }) = expr
+        else {
+            panic!("Expected expression with single child")
+        };
+        let step = *self.get_child().borrow();
+        *self.get_child().borrow_mut() += 1;
+        if step == 0 {
+            return Some(child);
+        }
+        None
+    }
+
+    fn handle_case_iter(&mut self, expr: &'nodes Expression) -> Option<&'nodes usize> {
+        let Expression::Case {
+            search_expr,
+            when_blocks,
+            else_expr,
+        } = expr
+        else {
+            panic!("Case expression expected");
+        };
+        let mut child_step = *self.get_child().borrow();
+        *self.get_child().borrow_mut() += 1;
+        if let Some(search_expr) = search_expr {
+            if child_step == 0 {
+                return Some(search_expr);
+            }
+            child_step -= 1;
+        }
+
+        let when_blocks_index = child_step / 2;
+        let index_reminder = child_step % 2;
+        return if when_blocks_index < when_blocks.len() {
+            let (cond_expr, res_expr) = when_blocks
+                .get(when_blocks_index)
+                .expect("When block must have been found.");
+            return match index_reminder {
+                0 => Some(cond_expr),
+                1 => Some(res_expr),
+                _ => unreachable!("Impossible reminder"),
+            };
+        } else if when_blocks_index == when_blocks.len() && index_reminder == 0 {
+            if let Some(else_expr) = else_expr {
+                Some(else_expr)
+            } else {
+                None
+            }
+        } else {
+            None
+        };
+    }
 }
 
 trait PlanTreeIterator<'plan>: TreeIterator<'plan> {
diff --git a/sbroad-core/src/ir/tree/expression.rs b/sbroad-core/src/ir/tree/expression.rs
index a9108cc24a66bf3224a4e0b8e77ccdab985a017f..b1621e2fe4c36f233aaad6dd724af848c5277a5f 100644
--- a/sbroad-core/src/ir/tree/expression.rs
+++ b/sbroad-core/src/ir/tree/expression.rs
@@ -101,148 +101,78 @@ impl<'n> Iterator for AggregateIterator<'n> {
 fn expression_next<'nodes>(
     iter: &mut impl ExpressionTreeIterator<'nodes>,
 ) -> Option<&'nodes usize> {
-    match iter.get_nodes().arena.get(iter.get_current()) {
-        Some(Node::Expression(
-            Expression::Alias { child, .. }
-            | Expression::ExprInParentheses { child, .. }
-            | Expression::Cast { child, .. }
-            | Expression::Unary { child, .. },
-        )) => {
-            let child_step = *iter.get_child().borrow();
-            if child_step == 0 {
-                *iter.get_child().borrow_mut() += 1;
-                return Some(child);
-            }
-            None
-        }
-        Some(Node::Expression(Expression::Case {
-            search_expr,
-            when_blocks,
-            else_expr,
-        })) => {
-            let mut child_step = *iter.get_child().borrow();
-            *iter.get_child().borrow_mut() += 1;
-            if let Some(search_expr) = search_expr {
-                if child_step == 0 {
-                    return Some(search_expr);
-                }
-                child_step -= 1;
-            }
-
-            let when_blocks_index = child_step / 2;
-            let index_reminder = child_step % 2;
-            return if when_blocks_index < when_blocks.len() {
-                let (cond_expr, res_expr) = when_blocks
-                    .get(when_blocks_index)
-                    .expect("When block must have been found.");
-                return match index_reminder {
-                    0 => Some(cond_expr),
-                    1 => Some(res_expr),
-                    _ => unreachable!("Impossible reminder"),
-                };
-            } else if when_blocks_index == when_blocks.len() && index_reminder == 0 {
-                if let Some(else_expr) = else_expr {
-                    Some(else_expr)
-                } else {
-                    None
-                }
-            } else {
-                None
-            };
-        }
-        Some(Node::Expression(
-            Expression::Bool { left, right, .. }
-            | Expression::Arithmetic { left, right, .. }
-            | Expression::Concat { left, right },
-        )) => {
-            let child_step = *iter.get_child().borrow();
-            if child_step == 0 {
-                *iter.get_child().borrow_mut() += 1;
-                return Some(left);
-            } else if child_step == 1 {
-                *iter.get_child().borrow_mut() += 1;
-                return Some(right);
-            }
-            None
-        }
-        Some(Node::Expression(Expression::Trim {
-            pattern, target, ..
-        })) => {
-            let child_step = *iter.get_child().borrow();
-            match child_step {
-                0 => {
-                    *iter.get_child().borrow_mut() += 1;
-                    match pattern {
-                        Some(_) => pattern.as_ref(),
-                        None => Some(target),
+    let node = iter.get_nodes().arena.get(iter.get_current());
+    match node {
+        Some(node) => {
+            match node {
+                Node::Expression(expr) => {
+                    match expr {
+                        Expression::Alias { .. }
+                        | Expression::ExprInParentheses { .. }
+                        | Expression::Cast { .. }
+                        | Expression::Unary { .. } => iter.handle_single_child(expr),
+                        Expression::Bool { .. }
+                        | Expression::Arithmetic { .. }
+                        | Expression::Concat { .. } => iter.handle_left_right_children(expr),
+                        Expression::Row { list, .. } => {
+                            let child_step = *iter.get_child().borrow();
+                            let mut is_leaf = false;
+
+                            // Check on the first step, if the row contains only leaf nodes.
+                            if child_step == 0 {
+                                is_leaf = true;
+                                for col in list {
+                                    if !matches!(
+                                        iter.get_nodes().arena.get(*col),
+                                        Some(Node::Expression(
+                                            Expression::Reference { .. }
+                                                | Expression::Constant { .. }
+                                        ))
+                                    ) {
+                                        is_leaf = false;
+                                        break;
+                                    }
+                                }
+                            }
+
+                            // If the row contains only leaf nodes (or we don't want to go deeper
+                            // into the row tree for some reasons), skip traversal.
+                            if !is_leaf || !iter.get_make_row_leaf() {
+                                match list.get(child_step) {
+                                    None => return None,
+                                    Some(child) => {
+                                        *iter.get_child().borrow_mut() += 1;
+                                        return Some(child);
+                                    }
+                                }
+                            }
+
+                            None
+                        }
+                        Expression::StableFunction { children, .. } => {
+                            let child_step = *iter.get_child().borrow();
+                            match children.get(child_step) {
+                                None => None,
+                                Some(child) => {
+                                    *iter.get_child().borrow_mut() += 1;
+                                    Some(child)
+                                }
+                            }
+                        }
+                        Expression::Trim { .. } => iter.handle_trim(expr),
+                        Expression::Case { .. } => iter.handle_case_iter(expr),
+                        Expression::Constant { .. }
+                        | Expression::Reference { .. }
+                        | Expression::CountAsterisk => None,
                     }
                 }
-                1 => {
-                    *iter.get_child().borrow_mut() += 1;
-                    match pattern {
-                        Some(_) => Some(target),
-                        None => None,
-                    }
-                }
-                _ => None,
-            }
-        }
-        Some(Node::Expression(Expression::Row { list, .. })) => {
-            let child_step = *iter.get_child().borrow();
-            let mut is_leaf = false;
-
-            // Check on the first step, if the row contains only leaf nodes.
-            if child_step == 0 {
-                is_leaf = true;
-                for col in list {
-                    if !matches!(
-                        iter.get_nodes().arena.get(*col),
-                        Some(Node::Expression(
-                            Expression::Reference { .. } | Expression::Constant { .. }
-                        ))
-                    ) {
-                        is_leaf = false;
-                        break;
-                    }
-                }
-            }
-
-            // If the row contains only leaf nodes (or we don't want to go deeper
-            // into the row tree for some reasons), skip traversal.
-            if !is_leaf || !iter.get_make_row_leaf() {
-                match list.get(child_step) {
-                    None => return None,
-                    Some(child) => {
-                        *iter.get_child().borrow_mut() += 1;
-                        return Some(child);
-                    }
-                }
-            }
-
-            None
-        }
-        Some(Node::Expression(Expression::StableFunction { children, .. })) => {
-            let child_step = *iter.get_child().borrow();
-            match children.get(child_step) {
-                None => None,
-                Some(child) => {
-                    *iter.get_child().borrow_mut() += 1;
-                    Some(child)
-                }
+                Node::Acl(_)
+                | Node::Block(_)
+                | Node::Ddl(_)
+                | Node::Relational(_)
+                | Node::Parameter => None,
             }
         }
-        Some(
-            Node::Expression(
-                Expression::Constant { .. }
-                | Expression::Reference { .. }
-                | Expression::CountAsterisk,
-            )
-            | Node::Relational(_)
-            | Node::Parameter
-            | Node::Ddl(_)
-            | Node::Acl(_)
-            | Node::Block(_),
-        )
-        | None => None,
+        None => None,
     }
 }
diff --git a/sbroad-core/src/ir/tree/subtree.rs b/sbroad-core/src/ir/tree/subtree.rs
index 5d3d4fda0c986c36199801136b71d61aff2b5f97..8066acbc6cf18b392ef38e9c52c665929924e2f5 100644
--- a/sbroad-core/src/ir/tree/subtree.rs
+++ b/sbroad-core/src/ir/tree/subtree.rs
@@ -196,88 +196,16 @@ fn subtree_next<'plan>(
     if let Some(child) = iter.get_nodes().arena.get(iter.get_current()) {
         return match child {
             Node::Parameter | Node::Ddl(..) | Node::Acl(..) | Node::Block(..) => None,
-            Node::Expression(exp) => match exp {
-                Expression::Alias { child, .. }
-                | Expression::ExprInParentheses { child }
-                | Expression::Cast { child, .. }
-                | Expression::Unary { child, .. } => {
-                    let step = *iter.get_child().borrow();
-                    *iter.get_child().borrow_mut() += 1;
-                    if step == 0 {
-                        return Some(child);
-                    }
-                    None
-                }
-                Expression::Case {
-                    search_expr,
-                    when_blocks,
-                    else_expr,
-                } => {
-                    let mut child_step = *iter.get_child().borrow();
-                    *iter.get_child().borrow_mut() += 1;
-                    if let Some(search_expr) = search_expr {
-                        if child_step == 0 {
-                            return Some(search_expr);
-                        }
-                        child_step -= 1;
-                    }
-
-                    let when_blocks_index = child_step / 2;
-                    let index_reminder = child_step % 2;
-                    return if when_blocks_index < when_blocks.len() {
-                        let (cond_expr, res_expr) = when_blocks
-                            .get(when_blocks_index)
-                            .expect("When block must have been found.");
-                        return match index_reminder {
-                            0 => Some(cond_expr),
-                            1 => Some(res_expr),
-                            _ => unreachable!("Impossible reminder"),
-                        };
-                    } else if when_blocks_index == when_blocks.len() && index_reminder == 0 {
-                        if let Some(else_expr) = else_expr {
-                            Some(else_expr)
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    };
-                }
-                Expression::Bool { left, right, .. }
-                | Expression::Arithmetic { left, right, .. }
-                | Expression::Concat { left, right } => {
-                    let child_step = *iter.get_child().borrow();
-                    if child_step == 0 {
-                        *iter.get_child().borrow_mut() += 1;
-                        return Some(left);
-                    } else if child_step == 1 {
-                        *iter.get_child().borrow_mut() += 1;
-                        return Some(right);
-                    }
-                    None
-                }
-                Expression::Trim {
-                    pattern, target, ..
-                } => {
-                    let child_step = *iter.get_child().borrow();
-                    match child_step {
-                        0 => {
-                            *iter.get_child().borrow_mut() += 1;
-                            match pattern {
-                                Some(_) => pattern.as_ref(),
-                                None => Some(target),
-                            }
-                        }
-                        1 => {
-                            *iter.get_child().borrow_mut() += 1;
-                            match pattern {
-                                Some(_) => Some(target),
-                                None => None,
-                            }
-                        }
-                        _ => None,
-                    }
-                }
+            Node::Expression(expr) => match expr {
+                Expression::Alias { .. }
+                | Expression::ExprInParentheses { .. }
+                | Expression::Cast { .. }
+                | Expression::Unary { .. } => iter.handle_single_child(expr),
+                Expression::Case { .. } => iter.handle_case_iter(expr),
+                Expression::Bool { .. }
+                | Expression::Arithmetic { .. }
+                | Expression::Concat { .. } => iter.handle_left_right_children(expr),
+                Expression::Trim { .. } => iter.handle_trim(expr),
                 Expression::Row { list, .. }
                 | Expression::StableFunction { children: list, .. } => {
                     let child_step = *iter.get_child().borrow();
@@ -299,7 +227,7 @@ fn subtree_next<'plan>(
                         // for selection filter or a join condition, we need to check whether
                         // the reference points to an **additional** sub-query and then traverse
                         // into it. Otherwise, stop traversal.
-                        let Ok(parent_id) = exp.get_parent() else {
+                        let Ok(parent_id) = expr.get_parent() else {
                             return None;
                         };
                         if let Ok(rel_id) = iter