diff --git a/src/ir.rs b/src/ir.rs
index 5e134826e32a93abb959928cb90c38d4e3c8b9c2..93a00e3654ae37586ea128ca967a0605cb0368ba 100644
--- a/src/ir.rs
+++ b/src/ir.rs
@@ -92,6 +92,129 @@ impl Plan {
         }
     }
 
+    /// Create a new tuple from the children nodes output, containing only
+    /// a specified list of column names. If the column list is empty then
+    /// just copy all the columns to a new tuple.
+    /// # Errors
+    /// Returns `QueryPlannerError`:
+    /// - relation node contains invalid `Row` in the output
+    /// - targets and children are inconsistent
+    /// - column names don't exits
+    pub fn add_row(
+        &mut self,
+        rel_node_id: usize,
+        children: &[usize],
+        targets: &[usize],
+        col_names: &[&str],
+    ) -> Result<usize, QueryPlannerError> {
+        // We can pass two target children nodes only in a case
+        // of `UnionAll`. Even for a `NaturalJoin` we work with
+        // each child independently. In fact, we need only the
+        // first child in a `UnionAll` operator to get correct
+        // column names for a new tuple (second child aliases
+        // would be shadowed). But each reference should point
+        // to both children to give us additional information
+        // during transformations.
+        if (targets.len() > 2) || targets.is_empty() {
+            return Err(QueryPlannerError::InvalidRow);
+        }
+
+        if let Some(max) = targets.iter().max() {
+            if *max >= children.len() {
+                return Err(QueryPlannerError::InvalidRow);
+            }
+        }
+
+        let target_child: usize = if let Some(target) = targets.get(0) {
+            *target
+        } else {
+            return Err(QueryPlannerError::InvalidRow);
+        };
+        let child_node: usize = if let Some(child) = children.get(target_child) {
+            *child
+        } else {
+            return Err(QueryPlannerError::InvalidRow);
+        };
+
+        if col_names.is_empty() {
+            let child_row_list: Vec<usize> =
+                if let Node::Relational(relational_op) = self.get_node(child_node)? {
+                    if let Node::Expression(Expression::Row { list, .. }) =
+                        self.get_node(relational_op.output())?
+                    {
+                        list.clone()
+                    } else {
+                        return Err(QueryPlannerError::InvalidRow);
+                    }
+                } else {
+                    return Err(QueryPlannerError::InvalidNode);
+                };
+
+            let mut aliases: Vec<usize> = Vec::new();
+
+            for (pos, alias_node) in child_row_list.iter().enumerate() {
+                let name: String = if let Node::Expression(Expression::Alias { ref name, .. }) =
+                    self.get_node(*alias_node)?
+                {
+                    String::from(name)
+                } else {
+                    return Err(QueryPlannerError::InvalidRow);
+                };
+                let new_targets: Vec<usize> = targets.iter().copied().collect();
+                // Create new references and aliases. Save them to the plan nodes arena.
+                let r_id = vec_alloc(
+                    &mut self.nodes,
+                    Node::Expression(Expression::new_ref(rel_node_id, Some(new_targets), pos)),
+                );
+                let a_id = vec_alloc(
+                    &mut self.nodes,
+                    Node::Expression(Expression::new_alias(&name, r_id)),
+                );
+                aliases.push(a_id);
+            }
+
+            let row_node = vec_alloc(
+                &mut self.nodes,
+                Node::Expression(Expression::new_row(aliases, None)),
+            );
+            return Ok(row_node);
+        }
+
+        let map = if let Node::Relational(relational_op) = self.get_node(child_node)? {
+            relational_op.output_alias_position_map(self)?
+        } else {
+            return Err(QueryPlannerError::InvalidNode);
+        };
+
+        let mut aliases: Vec<usize> = Vec::new();
+
+        let all_found = col_names.iter().all(|col| {
+            map.get(*col).map_or(false, |pos| {
+                let new_targets: Vec<usize> = targets.iter().copied().collect();
+                // Create new references and aliases. Save them to the plan nodes arena.
+                let r_id = vec_alloc(
+                    &mut self.nodes,
+                    Node::Expression(Expression::new_ref(rel_node_id, Some(new_targets), *pos)),
+                );
+                let a_id = vec_alloc(
+                    &mut self.nodes,
+                    Node::Expression(Expression::new_alias(col, r_id)),
+                );
+                aliases.push(a_id);
+                true
+            })
+        });
+
+        if all_found {
+            let row_node = vec_alloc(
+                &mut self.nodes,
+                Node::Expression(Expression::new_row(aliases, None)),
+            );
+            return Ok(row_node);
+        }
+        Err(QueryPlannerError::InvalidRow)
+    }
+
     /// Check that plan tree is valid.
     ///
     /// # Errors
@@ -187,7 +310,9 @@ impl Plan {
         if let Node::Expression(Expression::Row { list, .. }) = self.get_node(row_node)? {
             // Gather information about children nodes, that are pointed by the row references.
             for (pos, alias_node) in list.iter().enumerate() {
-                if let Node::Expression(Expression::Alias { child, .. }) = self.get_node(*alias_node)? {
+                if let Node::Expression(Expression::Alias { child, .. }) =
+                    self.get_node(*alias_node)?
+                {
                     if let Node::Expression(Expression::Reference {
                         targets,
                         position,
@@ -196,7 +321,8 @@ impl Plan {
                     }) = self.get_node(*child)?
                     {
                         // Get the relational node, containing this row
-                        parent_node = Some(*id_map.get(parent).ok_or(QueryPlannerError::InvalidNode)?);
+                        parent_node =
+                            Some(*id_map.get(parent).ok_or(QueryPlannerError::InvalidNode)?);
                         if let Node::Relational(relational_op) =
                             self.get_node(parent_node.ok_or(QueryPlannerError::InvalidNode)?)?
                         {
@@ -290,10 +416,12 @@ impl Plan {
                     Some(Distribution::Segment { key }) => {
                         let mut new_key: Vec<usize> = Vec::new();
                         let all_found = key.iter().all(|pos| {
-                            child_pos_map.get(&(child_rel_node, *pos)).map_or(false, |v| {
-                                new_key.push(*v);
-                                true
-                            })
+                            child_pos_map
+                                .get(&(child_rel_node, *pos))
+                                .map_or(false, |v| {
+                                    new_key.push(*v);
+                                    true
+                                })
                         });
                         if all_found {
                             return Ok(Distribution::Segment { key: new_key });
@@ -378,12 +506,12 @@ impl Plan {
         let right_child = *child_set_iter
             .next()
             .ok_or(QueryPlannerError::InvalidNode)?;
-    
+
         let is_union_all: bool = matches!(
             self.get_node(parent_node.ok_or(QueryPlannerError::InvalidNode)?)?,
             Node::Relational(Relational::UnionAll { .. })
         );
-    
+
         if is_union_all {
             let left_dist = self.dist_from_child(left_child, child_pos_map)?;
             let right_dist = self.dist_from_child(right_child, child_pos_map)?;
diff --git a/src/ir/operator.rs b/src/ir/operator.rs
index 954c483986bddc5af8c794e0fb77517ab5258383..210e9c7e9bbcf251b23fcc84e6136664faedbd34 100644
--- a/src/ir/operator.rs
+++ b/src/ir/operator.rs
@@ -112,129 +112,6 @@ pub enum Relational {
     },
 }
 
-/// Create a new tuple from the children nodes output, containing only
-/// a specified list of column names. If the column list is empty then
-/// just copy all the columns to a new tuple.
-/// # Errors
-/// Returns `QueryPlannerError`:
-/// - relation node contains invalid `Row` in the output
-/// - targets and children are inconsistent
-/// - column names don't exits
-pub fn new_row_node(
-    plan: &mut Plan,
-    rel_node_id: usize,
-    children: &[usize],
-    targets: &[usize],
-    col_names: &[&str],
-) -> Result<usize, QueryPlannerError> {
-    // We can pass two target children nodes only in a case
-    // of `UnionAll`. Even for a `NaturalJoin` we work with
-    // each child independently. In fact, we need only the
-    // first child in a `UnionAll` operator to get correct
-    // column names for a new tuple (second child aliases
-    // would be shadowed). But each reference should point
-    // to both children to give us additional information
-    // during transformations.
-    if (targets.len() > 2) || targets.is_empty() {
-        return Err(QueryPlannerError::InvalidRow);
-    }
-
-    if let Some(max) = targets.iter().max() {
-        if *max >= children.len() {
-            return Err(QueryPlannerError::InvalidRow);
-        }
-    }
-
-    let target_child: usize = if let Some(target) = targets.get(0) {
-        *target
-    } else {
-        return Err(QueryPlannerError::InvalidRow);
-    };
-    let child_node: usize = if let Some(child) = children.get(target_child) {
-        *child
-    } else {
-        return Err(QueryPlannerError::InvalidRow);
-    };
-
-    if col_names.is_empty() {
-        let child_row_list: Vec<usize> =
-            if let Node::Relational(relational_op) = plan.get_node(child_node)? {
-                if let Node::Expression(Expression::Row { list, .. }) =
-                    plan.get_node(relational_op.output())?
-                {
-                    list.clone()
-                } else {
-                    return Err(QueryPlannerError::InvalidRow);
-                }
-            } else {
-                return Err(QueryPlannerError::InvalidNode);
-            };
-
-        let mut aliases: Vec<usize> = Vec::new();
-
-        for (pos, alias_node) in child_row_list.iter().enumerate() {
-            let name: String = if let Node::Expression(Expression::Alias { ref name, .. }) =
-                plan.get_node(*alias_node)?
-            {
-                String::from(name)
-            } else {
-                return Err(QueryPlannerError::InvalidRow);
-            };
-            let new_targets: Vec<usize> = targets.iter().copied().collect();
-            // Create new references and aliases. Save them to the plan nodes arena.
-            let r_id = vec_alloc(
-                &mut plan.nodes,
-                Node::Expression(Expression::new_ref(rel_node_id, Some(new_targets), pos)),
-            );
-            let a_id = vec_alloc(
-                &mut plan.nodes,
-                Node::Expression(Expression::new_alias(&name, r_id)),
-            );
-            aliases.push(a_id);
-        }
-
-        let row_node = vec_alloc(
-            &mut plan.nodes,
-            Node::Expression(Expression::new_row(aliases, None)),
-        );
-        return Ok(row_node);
-    }
-
-    let map = if let Node::Relational(relational_op) = plan.get_node(child_node)? {
-        relational_op.output_alias_position_map(plan)?
-    } else {
-        return Err(QueryPlannerError::InvalidNode);
-    };
-
-    let mut aliases: Vec<usize> = Vec::new();
-
-    let all_found = col_names.iter().all(|col| {
-        map.get(*col).map_or(false, |pos| {
-            let new_targets: Vec<usize> = targets.iter().copied().collect();
-            // Create new references and aliases. Save them to the plan nodes arena.
-            let r_id = vec_alloc(
-                &mut plan.nodes,
-                Node::Expression(Expression::new_ref(rel_node_id, Some(new_targets), *pos)),
-            );
-            let a_id = vec_alloc(
-                &mut plan.nodes,
-                Node::Expression(Expression::new_alias(col, r_id)),
-            );
-            aliases.push(a_id);
-            true
-        })
-    });
-
-    if all_found {
-        let row_node = vec_alloc(
-            &mut plan.nodes,
-            Node::Expression(Expression::new_row(aliases, None)),
-        );
-        return Ok(row_node);
-    }
-    Err(QueryPlannerError::InvalidRow)
-}
-
 #[allow(dead_code)]
 impl Relational {
     /// Get an <column name - position> map from the output tuple.
@@ -372,7 +249,7 @@ impl Relational {
     ) -> Result<Self, QueryPlannerError> {
         let id = plan.next_node_id();
         let children: Vec<usize> = vec![child];
-        let output = new_row_node(plan, id, &children, &[0], col_names)?;
+        let output = plan.add_row(id, &children, &[0], col_names)?;
 
         Ok(Relational::Projection {
             children,
@@ -400,7 +277,7 @@ impl Relational {
 
         let id = plan.next_node_id();
         let children: Vec<usize> = vec![child];
-        let output = new_row_node(plan, id, &children, &[0], &[])?;
+        let output = plan.add_row(id, &children, &[0], &[])?;
 
         Ok(Relational::Selection {
             children,
@@ -439,7 +316,7 @@ impl Relational {
 
         let id = plan.next_node_id();
         let children: Vec<usize> = vec![left, right];
-        let output = new_row_node(plan, id, &children, &[0, 1], &[])?;
+        let output = plan.add_row(id, &children, &[0, 1], &[])?;
 
         Ok(Relational::UnionAll {
             children,
@@ -465,7 +342,7 @@ impl Relational {
         }
         let id = plan.next_node_id();
         let children: Vec<usize> = vec![child];
-        let output = new_row_node(plan, id, &children, &[0], &[])?;
+        let output = plan.add_row(id, &children, &[0], &[])?;
 
         Ok(Relational::ScanSubQuery {
             alias: String::from(alias),