From 7fd8b87ccc2d402cb72e10ced6022e746de9ec48 Mon Sep 17 00:00:00 2001
From: EmirVildanov <reddog201030@gmail.com>
Date: Tue, 3 Sep 2024 22:47:00 +0300
Subject: [PATCH] fix: refactoring after rebase on new protocol, tiers and
 subarenas

---
 sbroad-cartridge/src/cartridge/router.rs      |   2 +-
 .../test_app/test/integration/join_test.lua   |   2 +-
 .../subquery_as_expression_test.lua           |  23 +-
 .../test_app/test/integration/union_test.lua  |   2 +-
 sbroad-core/src/backend/sql/tree.rs           |  46 +--
 sbroad-core/src/executor/engine.rs            |   2 +-
 sbroad-core/src/executor/engine/helpers.rs    | 104 ++---
 sbroad-core/src/executor/engine/mock.rs       |  24 +-
 sbroad-core/src/executor/ir.rs                |   2 +-
 sbroad-core/src/executor/result.rs            |  12 +-
 sbroad-core/src/executor/result/tests.rs      |   2 +-
 sbroad-core/src/executor/tests.rs             |   8 +-
 sbroad-core/src/executor/tests/exec_plan.rs   | 218 ++---------
 sbroad-core/src/executor/vtable.rs            |  46 +--
 sbroad-core/src/executor/vtable/tests.rs      |  85 +---
 sbroad-core/src/frontend/sql.rs               |  52 ++-
 sbroad-core/src/frontend/sql/ir.rs            |  13 +-
 sbroad-core/src/frontend/sql/ir/tests.rs      |  53 ++-
 .../src/frontend/sql/ir/tests/global.rs       |  30 +-
 sbroad-core/src/ir.rs                         |  13 +-
 sbroad-core/src/ir/api/parameter.rs           |   4 +-
 sbroad-core/src/ir/distribution.rs            |  13 +-
 sbroad-core/src/ir/explain.rs                 |  27 +-
 sbroad-core/src/ir/expression.rs              |   8 +-
 sbroad-core/src/ir/helpers.rs                 | 368 +++++++++---------
 sbroad-core/src/ir/node.rs                    |   2 +-
 sbroad-core/src/ir/node/expression.rs         |   9 -
 sbroad-core/src/ir/node/relational.rs         |  62 +--
 sbroad-core/src/ir/operator.rs                |  50 +--
 sbroad-core/src/ir/operator/tests.rs          |   2 +-
 sbroad-core/src/ir/relation.rs                |   2 +-
 sbroad-core/src/ir/transformation/bool_in.rs  |   2 +-
 .../ir/transformation/equality_propagation.rs |   2 +-
 .../src/ir/transformation/redistribution.rs   |  31 +-
 .../ir/transformation/redistribution/dml.rs   |   6 +-
 .../transformation/redistribution/groupby.rs  |   4 +-
 .../redistribution/tests/segment.rs           |   1 -
 sbroad-core/src/ir/tree/relation.rs           |  19 +-
 sbroad-core/src/ir/tree/subtree.rs            |   4 +-
 sbroad-core/src/ir/tree/tests.rs              |   3 +-
 40 files changed, 560 insertions(+), 798 deletions(-)

diff --git a/sbroad-cartridge/src/cartridge/router.rs b/sbroad-cartridge/src/cartridge/router.rs
index cd69bc4911..8e5498d314 100644
--- a/sbroad-cartridge/src/cartridge/router.rs
+++ b/sbroad-cartridge/src/cartridge/router.rs
@@ -273,7 +273,7 @@ impl Router for RouterRuntime {
     fn materialize_values(
         &self,
         exec_plan: &mut ExecutionPlan,
-        values_id: usize,
+        values_id: NodeId,
     ) -> Result<VirtualTable, SbroadError> {
         materialize_values(self, exec_plan, values_id)
     }
diff --git a/sbroad-cartridge/test_app/test/integration/join_test.lua b/sbroad-cartridge/test_app/test/integration/join_test.lua
index 5781ddb0cb..d6a143a28f 100644
--- a/sbroad-cartridge/test_app/test/integration/join_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/join_test.lua
@@ -72,7 +72,7 @@ g.test_join_vtable_with_same_column_names = function()
         {name = "f", type = "integer"},
         {name = "s", type = "integer"},
     })
-    t.assert_equals(res.rows, {
+    t.assert_items_equals(res.rows, {
         {1, "a", 1, 1, 1},
         {2, "a", 1, 2, 2},
         {3, "a", 2, 3, 3},
diff --git a/sbroad-cartridge/test_app/test/integration/subquery_as_expression_test.lua b/sbroad-cartridge/test_app/test/integration/subquery_as_expression_test.lua
index eb322970cb..bff26f7980 100644
--- a/sbroad-cartridge/test_app/test/integration/subquery_as_expression_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/subquery_as_expression_test.lua
@@ -79,7 +79,7 @@ g.test_under_projection = function()
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "unsigned" },
+        { name = "col_1", type = "unsigned" },
     })
     t.assert_items_equals(r.rows, {
         { 1 }
@@ -91,8 +91,8 @@ g.test_under_projection = function()
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "unsigned" },
-        { name = "COL_2", type = "unsigned" },
+        { name = "col_1", type = "unsigned" },
+        { name = "col_2", type = "unsigned" },
     })
     t.assert_items_equals(r.rows, {
         { 1, 2 },
@@ -104,7 +104,7 @@ g.test_under_projection = function()
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "unsigned" },
+        { name = "col_1", type = "unsigned" },
     })
     t.assert_items_equals(r.rows, {
         { 3 },
@@ -116,7 +116,7 @@ g.test_under_projection = function()
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "integer" },
+        { name = "col_1", type = "integer" },
     })
     t.assert_items_equals(r.rows, {
         { 2 },
@@ -162,7 +162,7 @@ g.test_under_group_by = function()
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "decimal" },
+        { name = "col_1", type = "decimal" },
     })
     t.assert_items_equals(r.rows, {
         { 1 },
@@ -172,12 +172,15 @@ g.test_under_group_by = function()
 
     -- Single value in group by and having.
     r, err = api:call("sbroad.execute", { [[
-        SELECT sum("id") + 1, count(*) FROM "testing_space" GROUP BY "product_units" + (VALUES (1)) HAVING sum("id") + (VALUES (1)) > 7
+        SELECT sum("id") + 1, count(*)
+        FROM "testing_space"
+        GROUP BY "product_units" + (VALUES (1))
+        HAVING sum("id") + (VALUES (1)) > 7
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "decimal" },
-        { name = "COL_2", type = "decimal" },
+        { name = "col_1", type = "decimal" },
+        { name = "col_2", type = "decimal" },
     })
     t.assert_items_equals(r.rows, {
         { 10, 2 },
@@ -189,7 +192,7 @@ g.test_under_group_by = function()
     ]], {} })
     t.assert_equals(err, nil)
     t.assert_equals(r.metadata, {
-        { name = "COL_1", type = "decimal" },
+        { name = "col_1", type = "decimal" },
     })
     t.assert_items_equals(r.rows, {
         { 27 }
diff --git a/sbroad-cartridge/test_app/test/integration/union_test.lua b/sbroad-cartridge/test_app/test/integration/union_test.lua
index 3d9f39dae4..4b80896cbb 100644
--- a/sbroad-cartridge/test_app/test/integration/union_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/union_test.lua
@@ -216,7 +216,7 @@ union_queries.test_union_diff_types = function()
         union
         select "name" from "testing_space"
 ]], {} })
-    t.assert_str_contains(tostring(err), "failed to serialize value")
+    t.assert_str_contains(tostring(err), "Failed to cast '1' to integer.")
 end
 
 union_queries.test_union_empty_children = function()
diff --git a/sbroad-core/src/backend/sql/tree.rs b/sbroad-core/src/backend/sql/tree.rs
index d216104722..6977b07c36 100644
--- a/sbroad-core/src/backend/sql/tree.rs
+++ b/sbroad-core/src/backend/sql/tree.rs
@@ -1191,11 +1191,6 @@ impl<'p> SyntaxPlan<'p> {
         let _ = self.pop_from_stack(output_plan_id, id);
 
         let mut nodes = Vec::with_capacity(syntax_children.len() * 2 - 1);
-        // Reverse the order of the children back.
-        let first = sn_children.pop().expect("at least one child in VALUES");
-
-        // Consume the output from the stack.
-        self.pop_from_stack(output_plan_id, id);
 
         let arena = &mut self.nodes;
         for child_id in syntax_children.iter().skip(1).rev() {
@@ -1390,7 +1385,7 @@ impl<'p> SyntaxPlan<'p> {
             .get_expression_node(first_child_id)
             .expect("expression node expected");
         if matches!(first_list_child, Expression::Reference { .. }) {
-            let referred_rel_id = *plan
+            let referred_rel_id = plan
                 .get_relational_from_reference_node(first_child_id)
                 .expect("rel id expected");
             let referred_rel_node = plan
@@ -1432,7 +1427,7 @@ impl<'p> SyntaxPlan<'p> {
                             .get_expression_node(*child_id)
                             .expect("row child is expression");
                         if matches!(expr, Expression::Reference { .. }) {
-                            let referred_id = *plan
+                            let referred_id = plan
                                 .get_relational_from_reference_node(*child_id)
                                 .expect("referred id");
                             self.pop_from_stack(referred_id, id);
@@ -1474,7 +1469,7 @@ impl<'p> SyntaxPlan<'p> {
                             .get_expression_node(*child_id)
                             .expect("row child is expression");
                         if matches!(expr, Expression::Reference { .. }) {
-                            let referred_id = *plan
+                            let referred_id = plan
                                 .get_relational_from_reference_node(*child_id)
                                 .expect("referred id");
                             sq_sn_id = Some(self.pop_from_stack(referred_id, id));
@@ -1602,23 +1597,24 @@ impl<'p> SyntaxPlan<'p> {
             let sn_node = self.nodes.get_sn(sn_id);
             let sn_plan_node_pair = self.get_plan_node(&sn_node.data)?;
 
-            let nodes_to_add = if let Some((Node::Expression(node_expr), sn_plan_node_id)) =
-                sn_plan_node_pair
-            {
-                match node_expr {
-                    Expression::Alias(Alias { child, .. }) => handle_reference(sn_id, need_comma, *child),
-                    _ => handle_reference(sn_id, need_comma, sn_plan_node_id),
-                }
-            } else {
-                // As it's not ad Alias under Projection output, we don't have to
-                // dead with its machinery flags.
-                let mut nodes_to_add = Vec::new();
-                nodes_to_add.push(NodeToAdd::SnId(sn_id));
-                if need_comma {
-                    nodes_to_add.push(NodeToAdd::Comma)
-                }
-                nodes_to_add
-            };
+            let nodes_to_add =
+                if let Some((Node::Expression(node_expr), sn_plan_node_id)) = sn_plan_node_pair {
+                    match node_expr {
+                        Expression::Alias(Alias { child, .. }) => {
+                            handle_reference(sn_id, need_comma, *child)
+                        }
+                        _ => handle_reference(sn_id, need_comma, sn_plan_node_id),
+                    }
+                } else {
+                    // As it's not ad Alias under Projection output, we don't have to
+                    // dead with its machinery flags.
+                    let mut nodes_to_add = Vec::new();
+                    nodes_to_add.push(NodeToAdd::SnId(sn_id));
+                    if need_comma {
+                        nodes_to_add.push(NodeToAdd::Comma)
+                    }
+                    nodes_to_add
+                };
 
             for node in nodes_to_add {
                 match node {
diff --git a/sbroad-core/src/executor/engine.rs b/sbroad-core/src/executor/engine.rs
index 8ee4679148..778b4c8a5d 100644
--- a/sbroad-core/src/executor/engine.rs
+++ b/sbroad-core/src/executor/engine.rs
@@ -329,7 +329,7 @@ pub trait Router: QueryCache {
     fn materialize_values(
         &self,
         exec_plan: &mut ExecutionPlan,
-        values_id: usize,
+        values_id: NodeId,
     ) -> Result<VirtualTable, SbroadError>;
 }
 
diff --git a/sbroad-core/src/executor/engine/helpers.rs b/sbroad-core/src/executor/engine/helpers.rs
index 97bc459b0f..c0a2c8a092 100644
--- a/sbroad-core/src/executor/engine/helpers.rs
+++ b/sbroad-core/src/executor/engine/helpers.rs
@@ -3,19 +3,16 @@ use ahash::AHashMap;
 use crate::{
     error,
     ir::node::{
-        expression::{ExprOwned, Expression},
-        relational::{RelOwned, Relational},
-        Alias, Constant, Delete, Insert, Limit, Motion, NodeId, NodeOwned, Update, Values,
-        ValuesRow,
+        expression::Expression, relational::Relational, Alias, Constant, Delete, Insert, Limit,
+        Motion, NodeId, Update, Values, ValuesRow,
     },
     utils::MutexLike,
 };
-use itertools::enumerate;
 use smol_str::{format_smolstr, SmolStr, ToSmolStr};
 use std::{
     any::Any,
     cmp::Ordering,
-    collections::{HashMap, HashSet},
+    collections::HashMap,
     rc::Rc,
     str::{from_utf8, FromStr},
     sync::OnceLock,
@@ -31,9 +28,9 @@ use crate::backend::sql::space::{TableGuard, ADMIN_ID};
 use crate::executor::engine::helpers::storage::{execute_prepared, execute_unprepared, prepare};
 use crate::executor::engine::{QueryCache, StorageCache};
 use crate::executor::protocol::{EncodedTables, SchemaInfo};
+use crate::ir::node::Node;
 use crate::ir::operator::ConflictStrategy;
 use crate::ir::value::{EncodedValue, LuaValue, MsgPackValue};
-use crate::ir::{ExecuteOptions, Node, NodeId};
 use crate::otm::child_span;
 use crate::utils::ByteCounter;
 use crate::{
@@ -942,49 +939,6 @@ pub fn dispatch_by_buckets(
     }
 }
 
-/// Transform result of local Tarantool execution to `VirtualTable`.
-///
-/// # Errors
-/// - Unable to apply downcast.
-pub fn downcast_execution_result_to_vtable(
-    result: Box<dyn Any>,
-    column_names: Vec<SmolStr>,
-) -> Result<VirtualTable, SbroadError> {
-    if let Ok(tuple) = result.downcast::<Tuple>() {
-        let mut data = tuple.decode::<Vec<ProducerResult>>().map_err(|_| {
-            SbroadError::Invalid(
-                Entity::ProducerResult,
-                Some(format_smolstr!(
-                    "Unable to decode ProducerResult from tuple."
-                )),
-            )
-        })?;
-        data.get_mut(0)
-            .ok_or_else(|| {
-                SbroadError::Invalid(
-                    Entity::ProducerResult,
-                    Some("Unable to get producer result from the tuple".into()),
-                )
-            })?
-            .as_virtual_table(column_names)
-    } else {
-        return Ok(None);
-    };
-
-    // Check that the motion child is a values node with constants in the rows.
-    //
-    // When the VALUES node supports subqueries, arithmetics, etc. in addition
-    // to constants, we have to rewrite this code (need to check that there are
-    // no subqueries before node replacement).
-    let child_id = plan.get_motion_child(motion_node_id)?;
-    if !matches!(
-        plan.get_ir_plan().get_relation_node(child_id)?,
-        Relational::Values { .. }
-    ) {
-        return Ok(None);
-    }
-}
-
 /// Helper function reused for Cartridge/Picodata `materialize_values` method of Router.
 ///
 /// # Errors
@@ -995,14 +949,14 @@ pub fn downcast_execution_result_to_vtable(
 pub fn materialize_values(
     runtime: &impl Router,
     exec_plan: &mut ExecutionPlan,
-    values_id: usize,
+    values_id: NodeId,
 ) -> Result<VirtualTable, SbroadError> {
     let child_node = exec_plan.get_ir_plan().get_node(values_id)?;
 
-    let Node::Relational(Relational::Values {
+    let Node::Relational(Relational::Values(Values {
         ref children,
         output,
-    }) = child_node
+    })) = child_node
     else {
         panic!("Values node expected. Got {child_node:?}.")
     };
@@ -1017,33 +971,33 @@ pub fn materialize_values(
         .first()
         .expect("Values node must contain children.");
     let row_node = exec_plan.get_ir_plan().get_relation_node(*first_row_id)?;
-    let Relational::ValuesRow { data, .. } = row_node else {
+    let Relational::ValuesRow(ValuesRow { data, .. }) = row_node else {
         panic!("Expected ValuesRow, got {row_node:?}.")
     };
     let columns_len = exec_plan
         .get_ir_plan()
         .get_expression_node(*data)?
-        .get_row_list()
+        .get_row_list()?
         .len();
 
     // Flag indicating whether VALUES contains only constants.
     let mut only_constants = true;
     // Ids of constants that we have to replace with parameters.
     // We'll need to use it only in case
-    let mut constants_to_erase: Vec<usize> = Vec::new();
+    let mut constants_to_erase: Vec<NodeId> = Vec::new();
     for row_id in &children {
         let row_node = exec_plan.get_ir_plan().get_relation_node(*row_id)?;
-        let Relational::ValuesRow { data, .. } = row_node else {
+        let Relational::ValuesRow(ValuesRow { data, .. }) = row_node else {
             panic!("Expected ValuesRow under Values. Got {row_node:?}.")
         };
-        let data_row_list: Vec<usize> = exec_plan.get_ir_plan().get_row_list(*data)?.to_vec();
+        let data_row_list: Vec<NodeId> = exec_plan.get_ir_plan().get_row_list(*data)?.to_vec();
         let mut row: VTableTuple = Vec::with_capacity(columns_len);
         for idx in 0..columns_len {
             let column_id = *data_row_list
                 .get(idx)
                 .unwrap_or_else(|| panic!("Column not found at position {idx} in the row."));
             let column_node = exec_plan.get_ir_plan().get_node(column_id)?;
-            if let Node::Expression(Expression::Constant { value, .. }) = column_node {
+            if let Node::Expression(Expression::Constant(Constant { value, .. })) = column_node {
                 constants_to_erase.push(column_id);
                 row.push(value.clone());
             } else {
@@ -1059,13 +1013,10 @@ pub fn materialize_values(
     }
 
     let mut column_names: Vec<SmolStr> = Vec::new();
-    let output_cols = exec_plan
-        .get_ir_plan()
-        .get_expression_node(output)?
-        .get_row_list();
+    let output_cols = exec_plan.get_ir_plan().get_row_list(output)?;
     for column_id in output_cols {
         let alias = exec_plan.get_ir_plan().get_expression_node(*column_id)?;
-        if let Expression::Alias { name, .. } = alias {
+        if let Expression::Alias(Alias { name, .. }) = alias {
             column_names.push(name.clone());
         } else {
             panic!("Output column ({column_id}) is not an alias node.")
@@ -1075,8 +1026,7 @@ pub fn materialize_values(
     let mut vtable = if only_constants {
         // Otherwise `dispatch` call will replace nodes on Parameters.
         for column_id in constants_to_erase {
-            let column_node_ref = exec_plan.get_mut_ir_plan().get_mut_node(column_id)?;
-            let _ = std::mem::replace(column_node_ref, Node::Parameter(None));
+            let _ = exec_plan.get_mut_ir_plan().replace_with_stub(column_id);
         }
 
         // Create vtable columns with default column field (that will be fixed later).
@@ -1089,15 +1039,22 @@ pub fn materialize_values(
         vtable
     } else {
         // We need to execute VALUES as a local SQL.
-        let result = runtime.dispatch(exec_plan, values_id, &Buckets::Any)?;
-        downcast_execution_result_to_vtable(result, column_names)?
+        let mut result = runtime
+            .dispatch(
+                exec_plan,
+                values_id,
+                &Buckets::Any,
+                DispatchReturnFormat::Inner,
+            )?
+            .downcast::<ProducerResult>()
+            .expect("must've failed earlier");
+        result.as_virtual_table()?
     };
 
     let unified_types = calculate_vtable_unified_types(&vtable)?;
     vtable.cast_values(&unified_types)?;
 
-    let child_node_ref = exec_plan.get_mut_ir_plan().get_mut_node(values_id)?;
-    let _ = std::mem::replace(child_node_ref, Node::Parameter(None));
+    let _ = exec_plan.get_mut_ir_plan().replace_with_stub(values_id);
 
     Ok(vtable)
 }
@@ -1132,9 +1089,6 @@ pub fn materialize_motion(
     } else {
         panic!("Expected motion node, got {motion_node:?}");
     };
-    // We also need to find out, if the motion subtree contains values node
-    // (as a result we can retrieve incorrect types from the result metadata).
-    let possibly_incorrect_types = plan.get_ir_plan().subtree_contains_values(motion_node_id)?;
     // Dispatch the motion subtree (it will be replaced with invalid values).
     let mut result = *runtime
         .dispatch(plan, top_id, buckets, DispatchReturnFormat::Inner)?
@@ -1142,7 +1096,7 @@ pub fn materialize_motion(
         .expect("must've failed earlier");
     // Unlink motion node's child sub tree (it is already replaced with invalid values).
     plan.unlink_motion_subtree(motion_node_id)?;
-    let mut vtable = result.as_virtual_table(possibly_incorrect_types)?;
+    let mut vtable = result.as_virtual_table()?;
 
     if let Some(name) = alias {
         vtable.set_alias(name.as_str());
@@ -1644,7 +1598,7 @@ where
         .ok_or_else(|| SbroadError::NotFound(Entity::ProducerResult, "from the tuple".into()))?
         // It is a DML query, so we don't need to care about the column types
         // in response. So, simply use scalar type for all the columns.
-        .as_virtual_table(true)?;
+        .as_virtual_table()?;
     optional
         .exec_plan
         .set_motion_vtable(&child_id, vtable, runtime)?;
diff --git a/sbroad-core/src/executor/engine/mock.rs b/sbroad-core/src/executor/engine/mock.rs
index 805969cdf3..96cd81f698 100644
--- a/sbroad-core/src/executor/engine/mock.rs
+++ b/sbroad-core/src/executor/engine/mock.rs
@@ -1320,23 +1320,25 @@ impl Router for RouterRuntimeMock {
         motion_node_id: &NodeId,
         _buckets: &Buckets,
     ) -> Result<VirtualTable, SbroadError> {
-        if let Some(virtual_table) = self.virtual_tables.borrow().get(motion_node_id) {
-            Ok(virtual_table.clone())
-        } else {
-            panic!("Virtual table for motion with id {motion_node_id} not found.")
-        }
+        Ok(self
+            .virtual_tables
+            .borrow()
+            .get(motion_node_id)
+            .expect("Virtual table for motion with id {motion_node_id} not found.")
+            .clone())
     }
 
     fn materialize_values(
         &self,
         _exec_plan: &mut ExecutionPlan,
-        values_id: usize,
+        values_id: NodeId,
     ) -> Result<VirtualTable, SbroadError> {
-        if let Some(virtual_table) = self.virtual_tables.borrow().get(&values_id) {
-            Ok(virtual_table.clone())
-        } else {
-            panic!("Virtual table for values with id {values_id} not found.")
-        }
+        Ok(self
+            .virtual_tables
+            .borrow()
+            .get(&values_id)
+            .expect("Virtual table for values with id {values_id} not found.")
+            .clone())
     }
 
     fn dispatch(
diff --git a/sbroad-core/src/executor/ir.rs b/sbroad-core/src/executor/ir.rs
index 157c251e02..6e02205496 100644
--- a/sbroad-core/src/executor/ir.rs
+++ b/sbroad-core/src/executor/ir.rs
@@ -130,7 +130,7 @@ impl ExecutionPlan {
         self.vtables = Some(VirtualTableMap::new(vtables));
     }
 
-    pub fn contains_vtable_for_motion(&self, motion_id: usize) -> bool {
+    pub fn contains_vtable_for_motion(&self, motion_id: NodeId) -> bool {
         self.get_vtables()
             .map_or(false, |map| map.contains_key(&motion_id))
     }
diff --git a/sbroad-core/src/executor/result.rs b/sbroad-core/src/executor/result.rs
index 4227574602..7524e23d61 100644
--- a/sbroad-core/src/executor/result.rs
+++ b/sbroad-core/src/executor/result.rs
@@ -139,20 +139,12 @@ impl ProducerResult {
     ///
     /// # Errors
     /// - convert to virtual table error
-    pub fn as_virtual_table(
-        &mut self,
-        possibly_incorrect_types: bool,
-    ) -> Result<VirtualTable, SbroadError> {
+    pub fn as_virtual_table(&mut self) -> Result<VirtualTable, SbroadError> {
         let mut vtable = VirtualTable::new();
 
         // Decode metadata
         for col in &self.metadata {
-            let column: Column = if possibly_incorrect_types {
-                let column_type = Type::new_from_possibly_incorrect(&col.r#type)?;
-                Column::new(&col.name, column_type, ColumnRole::User, true)
-            } else {
-                col.try_into()?
-            };
+            let column: Column = col.try_into()?;
             vtable.add_column(VTableColumn {
                 r#type: column.r#type,
                 role: column.role,
diff --git a/sbroad-core/src/executor/result/tests.rs b/sbroad-core/src/executor/result/tests.rs
index db5ba1bca6..190fc198da 100644
--- a/sbroad-core/src/executor/result/tests.rs
+++ b/sbroad-core/src/executor/result/tests.rs
@@ -110,5 +110,5 @@ fn convert_to_vtable() {
         Value::from(decimal!(2.0)),
     ]);
 
-    assert_eq!(excepted, r.as_virtual_table(false).unwrap());
+    assert_eq!(excepted, r.as_virtual_table().unwrap());
 }
diff --git a/sbroad-core/src/executor/tests.rs b/sbroad-core/src/executor/tests.rs
index 60662c1b91..4acebfdc52 100644
--- a/sbroad-core/src/executor/tests.rs
+++ b/sbroad-core/src/executor/tests.rs
@@ -705,9 +705,9 @@ fn anonymous_col_index_test() {
                     r#"SELECT "test_space"."id", "test_space"."sysFrom", "test_space"."FIRST_NAME", "test_space"."sys_op""#,
                     r#"FROM "test_space""#,
                     r#"WHERE ("test_space"."id") in"#,
-                    r#"(SELECT "COL_1" FROM "TMP_test_1136")"#,
-                    r#"or ("test_space"."id") in"#,
                     r#"(SELECT "COL_1" FROM "TMP_test_0136")"#,
+                    r#"or ("test_space"."id") in"#,
+                    r#"(SELECT "COL_1" FROM "TMP_test_1136")"#,
                 ),
                 vec![],
             ))),
@@ -720,9 +720,9 @@ fn anonymous_col_index_test() {
                     "SELECT",
                     r#""test_space"."id", "test_space"."sysFrom", "test_space"."FIRST_NAME", "test_space"."sys_op" FROM "test_space""#,
                     r#"WHERE ("test_space"."id") in"#,
-                    r#"(SELECT "COL_1" FROM "TMP_test_1136")"#,
-                    r#"or ("test_space"."id") in"#,
                     r#"(SELECT "COL_1" FROM "TMP_test_0136")"#,
+                    r#"or ("test_space"."id") in"#,
+                    r#"(SELECT "COL_1" FROM "TMP_test_1136")"#,
                 ),
                 vec![],
             ))),
diff --git a/sbroad-core/src/executor/tests/exec_plan.rs b/sbroad-core/src/executor/tests/exec_plan.rs
index 796368eae9..121c84f2e1 100644
--- a/sbroad-core/src/executor/tests/exec_plan.rs
+++ b/sbroad-core/src/executor/tests/exec_plan.rs
@@ -19,7 +19,7 @@ use super::*;
 
 fn reshard_vtable(
     query: &Query<RouterRuntimeMock>,
-    motion_id: usize,
+    motion_id: NodeId,
     virtual_table: &mut VirtualTable,
 ) {
     if let MotionPolicy::Segment(key) = get_motion_policy(query.exec_plan.get_ir_plan(), motion_id)
@@ -168,7 +168,7 @@ fn exec_plan_subtree_two_stage_groupby_test_2() {
         sql,
         PatternWithParams::new(
             f_sql(
-                r#"SELECT "T1"."FIRST_NAME" as "column_12",
+                r#"SELECT "T1"."FIRST_NAME" as "column_596",
 "T1"."sys_op" as "column_696",
 "T1"."sysFrom" as "column_796"
 FROM "test_space" as "T1"
@@ -501,13 +501,7 @@ fn exec_plan_subtree_having() {
     let motion_child_id = exec_plan.get_motion_subtree_root(motion_id).unwrap();
 
     // Check groupby local stage
-    let sql = get_sql_from_execution_plan(
-        exec_plan,
-        motion_child_id,
-        Snapshot::Oldest,
-        &Buckets::All,
-        "test",
-    );
+    let sql = get_sql_from_execution_plan(exec_plan, motion_child_id, Snapshot::Oldest, TEMPLATE);
     if let MotionPolicy::Segment(_) = exec_plan.get_motion_policy(motion_id).unwrap() {
     } else {
         panic!("Expected MotionPolicy::Segment for local aggregation stage");
@@ -526,8 +520,7 @@ fn exec_plan_subtree_having() {
     );
 
     // Check main query
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
@@ -570,13 +563,7 @@ fn exec_plan_subtree_having_without_groupby() {
     let motion_child_id = exec_plan.get_motion_subtree_root(motion_id).unwrap();
 
     // Check groupby local stage
-    let sql = get_sql_from_execution_plan(
-        exec_plan,
-        motion_child_id,
-        Snapshot::Oldest,
-        &Buckets::All,
-        "test",
-    );
+    let sql = get_sql_from_execution_plan(exec_plan, motion_child_id, Snapshot::Oldest, TEMPLATE);
     if let MotionPolicy::Full = exec_plan.get_motion_policy(motion_id).unwrap() {
     } else {
         panic!("Expected MotionPolicy::Full after local stage");
@@ -596,8 +583,7 @@ fn exec_plan_subtree_having_without_groupby() {
     );
 
     // Check main query
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
@@ -621,12 +607,11 @@ fn exec_plan_subquery_as_expression_under_projection() {
     let exec_plan = query.get_mut_exec_plan();
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
 
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
-            format!("{}", r#"SELECT (VALUES (?)) as "COL_1" FROM "test_space""#,),
+            format!("{}", r#"SELECT (VALUES (?)) as "col_1" FROM "test_space""#,),
             vec![Value::Unsigned(1u64)]
         )
     );
@@ -641,14 +626,13 @@ fn exec_plan_subquery_as_expression_under_projection_several() {
     let exec_plan = query.get_mut_exec_plan();
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
 
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
             format!(
                 "{}",
-                r#"SELECT (VALUES (?)) as "COL_1", (VALUES (?)) as "COL_2" FROM "test_space""#,
+                r#"SELECT (VALUES (?)) as "col_1", (VALUES (?)) as "col_2" FROM "test_space""#,
             ),
             vec![Value::Unsigned(1u64), Value::Unsigned(2u64)]
         )
@@ -664,8 +648,7 @@ fn exec_plan_subquery_as_expression_under_selection() {
     let exec_plan = query.get_mut_exec_plan();
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
 
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
@@ -685,10 +668,10 @@ fn exec_plan_subquery_as_expression_under_order_by() {
 
     let mut query = Query::new(&coordinator, sql, vec![]).unwrap();
 
-    let mut vtables: HashMap<usize, Rc<VirtualTable>> = HashMap::new();
+    let mut vtables: HashMap<NodeId, Rc<VirtualTable>> = HashMap::new();
     let motion_id = query.get_motion_id(0, 0);
     let mut virtual_table = VirtualTable::new();
-    virtual_table.add_column(column_integer_user_non_null(SmolStr::from("COLUMN_1")));
+    virtual_table.add_column(vcolumn_integer_user_non_null());
     reshard_vtable(&query, motion_id, &mut virtual_table);
 
     vtables.insert(motion_id, Rc::new(virtual_table));
@@ -697,13 +680,7 @@ fn exec_plan_subquery_as_expression_under_order_by() {
     exec_plan.set_vtables(vtables);
 
     let motion_child_id = exec_plan.get_motion_subtree_root(motion_id).unwrap();
-    let sql = get_sql_from_execution_plan(
-        exec_plan,
-        motion_child_id,
-        Snapshot::Oldest,
-        &Buckets::All,
-        "test",
-    );
+    let sql = get_sql_from_execution_plan(exec_plan, motion_child_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
@@ -713,14 +690,13 @@ fn exec_plan_subquery_as_expression_under_order_by() {
     );
 
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
             format!(
                 "{}",
-                r#"SELECT "id" FROM (SELECT "COLUMN_1" FROM "TMP_test_6") ORDER BY ("id") + (VALUES (?))"#,
+                r#"SELECT "COL_1" as "id" FROM (SELECT "COL_1" FROM "TMP_test_0136") ORDER BY ("COL_1") + (VALUES (?))"#,
             ),
             vec![Value::Unsigned(1)]
         )
@@ -736,14 +712,13 @@ fn exec_plan_subquery_as_expression_under_projection_nested() {
     let exec_plan = query.get_mut_exec_plan();
 
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
             format!(
                 "{}",
-                r#"SELECT (VALUES ((VALUES (?)))) as "COL_1" FROM "test_space""#,
+                r#"SELECT (VALUES ((VALUES (?)))) as "col_1" FROM "test_space""#,
             ),
             vec![Value::Unsigned(1)]
         )
@@ -759,43 +734,36 @@ fn exec_plan_subquery_as_expression_under_group_by() {
 
     let motion_id = query.get_motion_id(0, 0);
     let mut virtual_table = VirtualTable::new();
-    virtual_table.add_column(column_integer_user_non_null(SmolStr::from("COLUMN_1")));
+    virtual_table.add_column(vcolumn_integer_user_non_null());
     reshard_vtable(&query, motion_id, &mut virtual_table);
 
-    let mut vtables: HashMap<usize, Rc<VirtualTable>> = HashMap::new();
+    let mut vtables: HashMap<NodeId, Rc<VirtualTable>> = HashMap::new();
     vtables.insert(motion_id, Rc::new(virtual_table));
 
     let exec_plan = query.get_mut_exec_plan();
     exec_plan.set_vtables(vtables);
 
     let motion_child_id = exec_plan.get_motion_subtree_root(motion_id).unwrap();
-    let sql = get_sql_from_execution_plan(
-        exec_plan,
-        motion_child_id,
-        Snapshot::Oldest,
-        &Buckets::All,
-        "test",
-    );
+    let sql = get_sql_from_execution_plan(exec_plan, motion_child_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
             format!(
                 "{}",
-                r#"SELECT ("test_space"."id") + (VALUES (?)) as "column_29", count (*) as "count_43" FROM "test_space" GROUP BY ("test_space"."id") + (VALUES (?))"#,
+                r#"SELECT ("test_space"."id") + (VALUES (?)) as "column_932", count (*) as "count_1496" FROM "test_space" GROUP BY ("test_space"."id") + (VALUES (?))"#,
             ),
             vec![Value::Unsigned(1u64), Value::Unsigned(1u64)]
         )
     );
 
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
             format!(
                 "{}",
-                r#"SELECT sum ("count_43") as "COL_1" FROM (SELECT "COLUMN_1" FROM "TMP_test_9") GROUP BY "column_29""#,
+                r#"SELECT sum ("count_1496") as "col_1" FROM (SELECT "COL_1" FROM "TMP_test_0136") GROUP BY "COL_1""#,
             ),
             vec![]
         )
@@ -815,8 +783,7 @@ fn global_table_scan() {
     let buckets = query.bucket_discovery(top_id).unwrap();
     assert_eq!(Buckets::Any, buckets);
     let exec_plan = query.get_mut_exec_plan();
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
+    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
         sql,
         PatternWithParams::new(
@@ -1060,7 +1027,7 @@ fn global_union_all3() {
         },
         ReplicasetDispatchInfo {
             rs_id: 1,
-            pattern: r#"SELECT "global_t"."a" FROM "global_t" WHERE ("global_t"."b") in (SELECT "COL_1" FROM "TMP_test_0136") UNION ALL SELECT "COL_1" as "f" FROM (SELECT "COL_1" FROM "TMP_test_35") GROUP BY "COL_1""#.to_string(),
+            pattern: r#"SELECT "global_t"."a" FROM "global_t" WHERE ("global_t"."b") in (SELECT "COL_1" FROM "TMP_test_0136") UNION ALL SELECT "COL_1" as "f" FROM (SELECT "COL_1" FROM "TMP_test_2136") GROUP BY "COL_1""#.to_string(),
             params: vec![],
             vtables_map: collection!(groupby_motion_id => Rc::new(groupby_vtable2), sq_motion_id => Rc::new(sq_vtable)),
         },
@@ -1253,91 +1220,6 @@ fn local_translation_asterisk_with_additional_columns() {
     );
 }
 
-#[test]
-fn local_translation_asterisk_single() {
-    let sql = r#"SELECT * from "t3""#;
-    let coordinator = RouterRuntimeMock::new();
-
-    let mut query = Query::new(&coordinator, sql, vec![]).unwrap();
-    let exec_plan = query.get_mut_exec_plan();
-    let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-
-    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
-    assert_eq!(
-        sql,
-        PatternWithParams::new(
-            format!("{}", r#"SELECT "t3"."a", "t3"."b" FROM "t3""#,),
-            vec![]
-        )
-    );
-}
-
-#[test]
-fn local_translation_asterisk_several() {
-    let sql = r#"SELECT *, * from "t3""#;
-    let coordinator = RouterRuntimeMock::new();
-
-    let mut query = Query::new(&coordinator, sql, vec![]).unwrap();
-    let exec_plan = query.get_mut_exec_plan();
-    let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-
-    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
-    assert_eq!(
-        sql,
-        PatternWithParams::new(
-            format!(
-                "{}",
-                r#"SELECT "t3"."a", "t3"."b", "t3"."a", "t3"."b" FROM "t3""#,
-            ),
-            vec![]
-        )
-    );
-}
-
-#[test]
-fn local_translation_asterisk_named() {
-    let sql = r#"SELECT *, "t3".*, * from "t3""#;
-    let coordinator = RouterRuntimeMock::new();
-
-    let mut query = Query::new(&coordinator, sql, vec![]).unwrap();
-    let exec_plan = query.get_mut_exec_plan();
-    let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-
-    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
-    assert_eq!(
-        sql,
-        PatternWithParams::new(
-            format!(
-                "{}",
-                r#"SELECT "t3"."a", "t3"."b", "t3"."a", "t3"."b", "t3"."a", "t3"."b" FROM "t3""#,
-            ),
-            vec![]
-        )
-    );
-}
-
-#[test]
-fn local_translation_asterisk_with_additional_columns() {
-    let sql = r#"SELECT "a", *, "t3"."b", "t3".*, * from "t3""#;
-    let coordinator = RouterRuntimeMock::new();
-
-    let mut query = Query::new(&coordinator, sql, vec![]).unwrap();
-    let exec_plan = query.get_mut_exec_plan();
-    let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-
-    let sql = get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, TEMPLATE);
-    assert_eq!(
-        sql,
-        PatternWithParams::new(
-            format!(
-                "{}",
-                r#"SELECT "t3"."a", "t3"."a", "t3"."b", "t3"."b", "t3"."a", "t3"."b", "t3"."a", "t3"."b" FROM "t3""#,
-            ),
-            vec![]
-        )
-    );
-}
-
 #[test]
 fn exec_plan_order_by() {
     let sql = r#"SELECT "identification_number" from "hash_testing"
@@ -1415,52 +1297,6 @@ fn exec_plan_order_by_with_subquery() {
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
     let motion_child_id = exec_plan.get_motion_subtree_root(motion_id).unwrap();
 
-    // Check sub-query
-    let sql = get_sql_from_execution_plan(
-        exec_plan,
-        motion_child_id,
-        Snapshot::Oldest,
-        &Buckets::All,
-        "test",
-    );
-    assert_eq!(
-        sql,
-        PatternWithParams::new(
-            r#"SELECT "hash_testing"."identification_number" FROM "hash_testing""#.to_string(),
-            vec![]
-        )
-    );
-
-    // Check main query
-    let sql =
-        get_sql_from_execution_plan(exec_plan, top_id, Snapshot::Oldest, &Buckets::All, "test");
-    assert_eq!(
-        sql,
-        PatternWithParams::new(
-            r#"SELECT "COL_1" as "identification_number" FROM (SELECT "COL_1" FROM "TMP_test_6") as "hash_testing" ORDER BY "COL_1""#.to_string(),
-            vec![]
-        ));
-}
-
-#[test]
-fn exec_plan_order_by_with_subquery() {
-    let sql = r#"SELECT "identification_number"
-                      FROM (select "identification_number" from "hash_testing")
-                      ORDER BY "identification_number""#;
-    let coordinator = RouterRuntimeMock::new();
-
-    let mut query = Query::new(&coordinator, sql, vec![]).unwrap();
-    let motion_id = query.get_motion_id(0, 0);
-    let mut virtual_table = virtual_table_23(None);
-    reshard_vtable(&query, motion_id, &mut virtual_table);
-    let mut vtables: HashMap<usize, Rc<VirtualTable>> = HashMap::new();
-    vtables.insert(motion_id, Rc::new(virtual_table));
-
-    let exec_plan = query.get_mut_exec_plan();
-    exec_plan.set_vtables(vtables);
-    let top_id = exec_plan.get_ir_plan().get_top().unwrap();
-    let motion_child_id = exec_plan.get_motion_subtree_root(motion_id).unwrap();
-
     // Check sub-query
     let sql = get_sql_from_execution_plan(exec_plan, motion_child_id, Snapshot::Oldest, TEMPLATE);
     assert_eq!(
@@ -1476,7 +1312,7 @@ fn exec_plan_order_by_with_subquery() {
     assert_eq!(
         sql,
         PatternWithParams::new(
-            r#"SELECT "COL_1" as "identification_number" FROM (SELECT "COL_1" FROM "TMP_test_0136") ORDER BY "COL_1""#.to_string(),
+            r#"SELECT "COL_1" as "identification_number" FROM (SELECT "COL_1" FROM "TMP_test_0136") as "hash_testing" ORDER BY "COL_1""#.to_string(),
             vec![]
         ));
 }
diff --git a/sbroad-core/src/executor/vtable.rs b/sbroad-core/src/executor/vtable.rs
index b0314bfb51..7579535cf1 100644
--- a/sbroad-core/src/executor/vtable.rs
+++ b/sbroad-core/src/executor/vtable.rs
@@ -194,8 +194,8 @@ impl VirtualTable {
         for tuple in self.get_mut_tuples() {
             for (i, v) in tuple.iter_mut().enumerate() {
                 let (_, ty) = fixed_types.get(i).expect("Type expected.");
-                let casted_value = v.cast(ty)?;
-                match casted_value {
+                let cast_value = v.cast(ty)?;
+                match cast_value {
                     EncodedValue::Ref(_) => {
                         // Value type is already ok.
                     }
@@ -762,26 +762,28 @@ pub fn calculate_vtable_unified_types(
     vtable: &VirtualTable,
 ) -> Result<Vec<(bool, Type)>, SbroadError> {
     // Map of { type -> types_which_can_be_upcasted_to_given_one }.
-    let get_types_less = |ty: &Type| match ty {
-        Type::Scalar
-        | Type::Any
-        | Type::Map
-        | Type::Array
-        | Type::Boolean
-        | Type::String
-        | Type::Datetime => vec![],
-        Type::Uuid => vec![Type::String],
-        Type::Unsigned => vec![Type::Scalar],
-        Type::Integer => vec![Type::Scalar, Type::Unsigned],
-        Type::Double => vec![Type::Scalar, Type::Unsigned, Type::Integer],
-        Type::Decimal => vec![Type::Scalar, Type::Unsigned, Type::Integer, Type::Double],
-        Type::Number => vec![
-            Type::Scalar,
-            Type::Unsigned,
-            Type::Integer,
-            Type::Double,
-            Type::Decimal,
-        ],
+    let get_types_less = |ty: &Type| -> &[Type] {
+        match ty {
+            Type::Scalar
+            | Type::Any
+            | Type::Map
+            | Type::Array
+            | Type::Boolean
+            | Type::String
+            | Type::Datetime => &[],
+            Type::Uuid => &[Type::String],
+            Type::Unsigned => &[Type::Scalar],
+            Type::Integer => &[Type::Scalar, Type::Unsigned],
+            Type::Double => &[Type::Scalar, Type::Unsigned, Type::Integer],
+            Type::Decimal => &[Type::Scalar, Type::Unsigned, Type::Integer, Type::Double],
+            Type::Number => &[
+                Type::Scalar,
+                Type::Unsigned,
+                Type::Integer,
+                Type::Double,
+                Type::Decimal,
+            ],
+        }
     };
 
     let columns_len = vtable.columns.len();
diff --git a/sbroad-core/src/executor/vtable/tests.rs b/sbroad-core/src/executor/vtable/tests.rs
index 9216b64d84..fb825abddd 100644
--- a/sbroad-core/src/executor/vtable/tests.rs
+++ b/sbroad-core/src/executor/vtable/tests.rs
@@ -335,17 +335,13 @@ fn vtable_remove_duplicates3() {
 fn vtable_values_types_casting_single_tuple() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1)]);
     let unified_types = calculate_vtable_unified_types(&actual_vtable).unwrap();
     actual_vtable.cast_values(&unified_types).unwrap();
 
     let mut expected_vtable = VirtualTable::new();
-    expected_vtable.add_column(Column {
-        name: first_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Unsigned,
         role: ColumnRole::User,
         is_nullable: false,
@@ -359,18 +355,14 @@ fn vtable_values_types_casting_single_tuple() {
 fn vtable_values_types_casting_two_tuples() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1)]);
     actual_vtable.add_tuple(vec![Value::Integer(1)]);
     let unified_types = calculate_vtable_unified_types(&actual_vtable).unwrap();
     actual_vtable.cast_values(&unified_types).unwrap();
 
     let mut expected_vtable = VirtualTable::new();
-    expected_vtable.add_column(Column {
-        name: first_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Integer,
         role: ColumnRole::User,
         is_nullable: false,
@@ -385,10 +377,7 @@ fn vtable_values_types_casting_two_tuples() {
 fn vtable_values_types_casting_two_tuples_err() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1)]);
     actual_vtable.add_tuple(vec![Value::String("name".into())]);
     let err = calculate_vtable_unified_types(&actual_vtable).unwrap_err();
@@ -404,27 +393,19 @@ fn vtable_values_types_casting_two_tuples_err() {
 fn vtable_values_types_casting_two_columns() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    let second_column_name = "b";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        second_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1), Value::Integer(1)]);
     let unified_types = calculate_vtable_unified_types(&actual_vtable).unwrap();
     actual_vtable.cast_values(&unified_types).unwrap();
 
     let mut expected_vtable = VirtualTable::new();
-    expected_vtable.add_column(Column {
-        name: first_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Unsigned,
         role: ColumnRole::User,
         is_nullable: false,
     });
-    expected_vtable.add_column(Column {
-        name: second_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Integer,
         role: ColumnRole::User,
         is_nullable: false,
@@ -438,28 +419,20 @@ fn vtable_values_types_casting_two_columns() {
 fn vtable_values_types_casting_two_columns_two_tuples() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    let second_column_name = "b";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        second_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1), Value::Integer(1)]);
     actual_vtable.add_tuple(vec![Value::Decimal(Decimal::from(2)), Value::Integer(1)]);
     let unified_types = calculate_vtable_unified_types(&actual_vtable).unwrap();
     actual_vtable.cast_values(&unified_types).unwrap();
 
     let mut expected_vtable = VirtualTable::new();
-    expected_vtable.add_column(Column {
-        name: first_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Decimal,
         role: ColumnRole::User,
         is_nullable: false,
     });
-    expected_vtable.add_column(Column {
-        name: second_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Integer,
         role: ColumnRole::User,
         is_nullable: false,
@@ -474,14 +447,8 @@ fn vtable_values_types_casting_two_columns_two_tuples() {
 fn vtable_values_types_casting_two_columns_with_nulls() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    let second_column_name = "b";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        second_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1), Value::Null]);
     actual_vtable.add_tuple(vec![Value::Null, Value::Null]);
     actual_vtable.add_tuple(vec![Value::Decimal(Decimal::from(2)), Value::Null]);
@@ -489,14 +456,12 @@ fn vtable_values_types_casting_two_columns_with_nulls() {
     actual_vtable.cast_values(&unified_types).unwrap();
 
     let mut expected_vtable = VirtualTable::new();
-    expected_vtable.add_column(Column {
-        name: first_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Decimal,
         role: ColumnRole::User,
         is_nullable: true,
     });
-    expected_vtable.add_column(Column {
-        name: second_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Integer,
         role: ColumnRole::User,
         is_nullable: true,
@@ -512,14 +477,8 @@ fn vtable_values_types_casting_two_columns_with_nulls() {
 fn vtable_values_types_casting_two_columns_numerical() {
     let mut actual_vtable = VirtualTable::new();
 
-    let first_column_name = "a";
-    let second_column_name = "b";
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        first_column_name,
-    )));
-    actual_vtable.add_column(column_integer_user_non_null(SmolStr::from(
-        second_column_name,
-    )));
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
+    actual_vtable.add_column(vcolumn_integer_user_non_null());
     actual_vtable.add_tuple(vec![Value::Unsigned(1), Value::Integer(1)]);
     actual_vtable.add_tuple(vec![Value::Null, Value::Unsigned(5)]);
     actual_vtable.add_tuple(vec![Value::Integer(1), Value::Null]);
@@ -535,14 +494,12 @@ fn vtable_values_types_casting_two_columns_numerical() {
     actual_vtable.cast_values(&unified_types).unwrap();
 
     let mut expected_vtable = VirtualTable::new();
-    expected_vtable.add_column(Column {
-        name: first_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Decimal,
         role: ColumnRole::User,
         is_nullable: true,
     });
-    expected_vtable.add_column(Column {
-        name: second_column_name.into(),
+    expected_vtable.add_column(VTableColumn {
         r#type: Type::Decimal,
         role: ColumnRole::User,
         is_nullable: true,
diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs
index b6bb57cf54..8db4236a09 100644
--- a/sbroad-core/src/frontend/sql.rs
+++ b/sbroad-core/src/frontend/sql.rs
@@ -3,7 +3,7 @@
 //! Parses an SQL statement to the abstract syntax tree (AST)
 //! and builds the intermediate representation (IR).
 
-use crate::ir::node::ReferenceAsteriskSource;
+use crate::ir::node::{Reference, ReferenceAsteriskSource};
 use ahash::{AHashMap, AHashSet};
 use core::panic;
 use itertools::Itertools;
@@ -1507,13 +1507,13 @@ const PARSING_PAIRS_MAP_CAPACITY: usize = 100;
 /// `left >= center AND left <= right`.
 struct Between {
     /// Left node id.
-    left_id: usize,
+    left_id: NodeId,
     /// LEQ node id (`left <= right`)
-    leq_id: usize,
+    leq_id: NodeId,
 }
 
 impl Between {
-    fn new(left_id: usize, less_eq_id: usize) -> Self {
+    fn new(left_id: NodeId, less_eq_id: NodeId) -> Self {
         Self {
             left_id,
             leq_id: less_eq_id,
@@ -1543,14 +1543,14 @@ where
     /// We can't fix between child (clone expression subtree) in the place of their creation,
     /// because we'll copy references without adequate `parent` and `target` that we couldn't fix
     /// later.
-    subquery_replaces: AHashMap<usize, usize>,
+    subquery_replaces: AHashMap<NodeId, NodeId>,
     /// Vec of { (sq_id, ref_ids_to_fix_parent_and_target) }
     /// After calling `parse_expr` and creating relational node that can contain SubQuery as
     /// additional child (Selection, Join, Having, OrderBy, GroupBy, Projection) we should pop the
     /// queue till it's not empty and:
     /// * Add subqueries to the list of relational children
     /// * Fix References
-    sub_queries_to_fix_queue: VecDeque<(usize, Vec<usize>)>,
+    sub_queries_to_fix_queue: VecDeque<(NodeId, Vec<NodeId>)>,
     metadata: &'worker M,
     /// Map of { reference plan_id -> (it's column name, whether it's covered with row)}
     /// We have to save column name in order to use it later for alias creation.
@@ -1634,13 +1634,13 @@ where
     /// nothing is left for the `left <= right` sutree.
     pub(super) fn fix_betweens(&self, plan: &mut Plan) -> Result<(), SbroadError> {
         for between in &self.betweens {
-            let left_id: usize = if let Some(id) = self.subquery_replaces.get(&between.left_id) {
+            let left_id = if let Some(id) = self.subquery_replaces.get(&between.left_id) {
                 plan.clone_expr_subtree(*id)?
             } else {
                 plan.clone_expr_subtree(between.left_id)?
             };
             let less_eq_expr = plan.get_mut_expression_node(between.leq_id)?;
-            if let Expression::Bool { ref mut left, .. } = less_eq_expr {
+            if let MutExpression::Bool(BoolExpr { ref mut left, .. }) = less_eq_expr {
                 *left = left_id;
             } else {
                 panic!("Expected to see LEQ expression.")
@@ -1663,7 +1663,7 @@ enum ParseExpression {
         plan_id: NodeId,
     },
     SubQueryPlanId {
-        plan_id: usize,
+        plan_id: NodeId,
     },
     Parentheses {
         child: Box<ParseExpression>,
@@ -1783,10 +1783,10 @@ impl Plan {
     /// Helper function to populate plan with `SubQuery` represented as a Row of its output.
     fn add_replaced_subquery<M: Metadata>(
         &mut self,
-        sq_id: usize,
+        sq_id: NodeId,
         expected_output_size: Option<usize>,
         worker: &mut ExpressionsWorker<M>,
-    ) -> Result<usize, SbroadError> {
+    ) -> Result<NodeId, SbroadError> {
         let (sq_row_id, new_refs) = self.add_row_from_subquery(sq_id, expected_output_size)?;
         worker.subquery_replaces.insert(sq_id, sq_row_id);
         worker.sub_queries_to_fix_queue.push_back((sq_id, new_refs));
@@ -1798,25 +1798,21 @@ impl Plan {
     fn fix_subquery_rows<M: Metadata>(
         &mut self,
         worker: &mut ExpressionsWorker<M>,
-        rel_id: usize,
+        rel_id: NodeId,
     ) -> Result<(), SbroadError> {
-        let rel_node = self.get_mut_relation_node(rel_id)?;
+        let mut rel_node = self.get_mut_relation_node(rel_id)?;
 
-        let mut rel_node_children_len = rel_node.children().len();
+        let mut rel_node_children_len = rel_node.mut_children().len();
         for (sq_id, _) in &worker.sub_queries_to_fix_queue {
             rel_node.add_sq_child(*sq_id);
         }
 
-        while !worker.sub_queries_to_fix_queue.is_empty() {
-            let (_, new_refs) = worker
-                .sub_queries_to_fix_queue
-                .pop_front()
-                .expect("Expected to get res on non-empty `sub_queries_to_fix_queue`.");
+        while let Some((_, new_refs)) = worker.sub_queries_to_fix_queue.pop_front() {
             for new_ref_id in new_refs {
                 let new_ref = self.get_mut_expression_node(new_ref_id)?;
-                if let Expression::Reference {
+                if let MutExpression::Reference(Reference {
                     parent, targets, ..
-                } = new_ref
+                }) = new_ref
                 {
                     *parent = Some(rel_id);
                     *targets = Some(vec![rel_node_children_len]);
@@ -2128,7 +2124,7 @@ impl ParseExpression {
                     let uncovered_plan_child_id = if let Some((_, is_row)) = reference {
                         if *is_row {
                             let plan_inner_expr = plan.get_expression_node(plan_child_id)?;
-                            *plan_inner_expr.get_row_list().first().ok_or_else(|| {
+                            *plan_inner_expr.get_row_list()?.first().ok_or_else(|| {
                                 SbroadError::UnexpectedNumberOfValues(
                                     "There must be a Reference under Row.".into(),
                                 )
@@ -2375,9 +2371,10 @@ where
 
                     let plan_left_id = referred_relation_ids
                         .first()
-                        .unwrap_or_else(||
-                            panic!("Reference must point to some relational node")
-                        );
+                        .ok_or(SbroadError::Invalid(
+                            Entity::Query,
+                            Some("Reference must point to some relational node".into())
+                        ))?;
 
                     worker.build_columns_map(plan, *plan_left_id)?;
 
@@ -3228,7 +3225,7 @@ impl AbstractSyntaxTree {
                             PostOrder::with_capacity(|node| plan.nodes.expr_iter(node, false), EXPR_CAPACITY);
                         let mut reference_met = false;
                         for LevelNode(_, node_id) in expr_tree.iter(expr_plan_node_id) {
-                            if let Expression::Reference { targets, .. } = plan.get_expression_node(node_id)? {
+                            if let Expression::Reference(Reference { targets, .. }) = plan.get_expression_node(node_id)? {
                                 if targets.is_some() {
                                     // Subquery reference met.
                                     reference_met = true;
@@ -3274,7 +3271,8 @@ impl AbstractSyntaxTree {
 
             order_by_elements.push(OrderByElement { entity, order_type });
         }
-        let (order_by_id, plan_node_id) = plan.add_order_by(projection_plan_id, order_by_elements)?;
+        let (order_by_id, plan_node_id) =
+            plan.add_order_by(projection_plan_id, order_by_elements)?;
         plan.fix_subquery_rows(worker, order_by_id)?;
         map.add(node_id, plan_node_id);
         Ok(())
diff --git a/sbroad-core/src/frontend/sql/ir.rs b/sbroad-core/src/frontend/sql/ir.rs
index 6bf520cfa8..4e40897820 100644
--- a/sbroad-core/src/frontend/sql/ir.rs
+++ b/sbroad-core/src/frontend/sql/ir.rs
@@ -7,14 +7,13 @@ use tarantool::decimal::Decimal;
 
 use crate::errors::{Entity, SbroadError};
 use crate::frontend::sql::ast::Rule;
-use crate::ir::helpers::RepeatableState;
-use crate::ir::node::expression::{ExprOwned, Expression, MutExpression};
+use crate::ir::node::expression::{ExprOwned, Expression};
 use crate::ir::node::relational::{MutRelational, RelOwned, Relational};
 use crate::ir::node::{
-    Alias, ArenaType, ArithmeticExpr, BoolExpr, Case, Cast, Concat, Constant, Delete, Except,
-    ExprInParentheses, GroupBy, Having, Insert, Intersect, Join, Limit, Motion, MutNode, Node,
-    NodeAligned, NodeId, OrderBy, Projection, Reference, Row, ScanCte, ScanRelation, ScanSubQuery,
-    Selection, StableFunction, Trim, UnaryExpr, Union, UnionAll, Update, Values, ValuesRow,
+    Alias, ArithmeticExpr, BoolExpr, Case, Cast, Concat, Constant, Delete, Except,
+    ExprInParentheses, GroupBy, Having, Insert, Intersect, Join, Limit, Motion, Node, NodeAligned,
+    NodeId, OrderBy, Projection, Reference, Row, ScanCte, ScanRelation, ScanSubQuery, Selection,
+    StableFunction, Trim, UnaryExpr, Union, UnionAll, Update, Values, ValuesRow,
 };
 use crate::ir::operator::{OrderByElement, OrderByEntity};
 use crate::ir::transformation::redistribution::MotionOpcode;
@@ -141,7 +140,7 @@ impl CloneExprSubtreeMap {
 }
 
 impl Plan {
-    pub(crate) fn clone_expr_subtree(&mut self, top_id: usize) -> Result<usize, SbroadError> {
+    pub(crate) fn clone_expr_subtree(&mut self, top_id: NodeId) -> Result<NodeId, SbroadError> {
         let mut subtree =
             PostOrder::with_capacity(|node| self.nodes.expr_iter(node, false), EXPR_CAPACITY);
         subtree.populate_nodes(top_id);
diff --git a/sbroad-core/src/frontend/sql/ir/tests.rs b/sbroad-core/src/frontend/sql/ir/tests.rs
index ebe7cc8798..cb2cf1e9ef 100644
--- a/sbroad-core/src/frontend/sql/ir/tests.rs
+++ b/sbroad-core/src/frontend/sql/ir/tests.rs
@@ -1618,7 +1618,6 @@ fn front_sql_avg_aggregate() {
     let input = r#"SELECT avg("b"), avg(distinct "b"), avg("b") * avg("b") FROM "t""#;
 
     let plan = sql_to_optimized_ir(input, vec![]);
-    println!("{}", plan.as_explain().unwrap());
 
     let expected_explain = String::from(
         r#"projection (sum(("sum_696"::decimal::double))::decimal / sum(("count_696"::decimal::double))::decimal -> "col_1", avg(distinct ("column_796"::decimal::double))::decimal -> "col_2", ROW(sum(("sum_696"::decimal::double))::decimal / sum(("count_696"::decimal::double))::decimal) * ROW(sum(("sum_696"::decimal::double))::decimal / sum(("count_696"::decimal::double))::decimal) -> "col_3")
@@ -1810,7 +1809,6 @@ fn front_sql_aggregates_with_subexpressions() {
         group by "b""#;
 
     let plan = sql_to_optimized_ir(input, vec![]);
-    println!("{}", plan.as_explain().unwrap());
 
     let expected_explain = String::from(
         r#"projection ("column_596"::unsigned -> "b", sum(("count_1496"::integer))::decimal -> "col_1", sum(("count_1796"::integer))::decimal -> "col_2")
@@ -2133,7 +2131,6 @@ fn front_sql_aggregate_on_aggregate() {
     let input = r#"SELECT max(c) FROM (SELECT count("id") as c FROM "test_space") as "t1""#;
 
     let plan = sql_to_optimized_ir(input, vec![]);
-    println!("{}", plan.as_explain().unwrap());
 
     let expected_explain = String::from(
         r#"projection (max(("t1"."c"::integer))::scalar -> "col_1")
@@ -2351,7 +2348,6 @@ fn front_sql_except_single_both() {
     "#;
 
     let plan = sql_to_optimized_ir(input, vec![]);
-    println!("{}", plan.as_explain().unwrap());
     let expected_explain = String::from(
         r#"except
     motion [policy: segment([ref("col_1")])]
@@ -2762,11 +2758,11 @@ fn front_sql_having_with_sq() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection ("column_596"::unsigned -> "sysFrom", sum(distinct ("column_3296"::decimal))::decimal -> "sum", count(distinct ("column_3296"::integer))::integer -> "count")
-    having ROW($0) > ROW(count(distinct ("column_3296"::integer))::integer)
-        group by ("column_596"::unsigned) output: ("column_596"::unsigned -> "column_596", "column_3296"::unsigned -> "column_3296")
+        r#"projection ("column_596"::unsigned -> "sysFrom", sum(distinct ("column_3396"::decimal))::decimal -> "sum", count(distinct ("column_3396"::integer))::integer -> "count")
+    having ROW($0) > ROW(count(distinct ("column_3396"::integer))::integer)
+        group by ("column_596"::unsigned) output: ("column_596"::unsigned -> "column_596", "column_3396"::unsigned -> "column_3396")
             motion [policy: segment([ref("column_596")])]
-                projection ("test_space"."sysFrom"::unsigned -> "column_596", "test_space"."id"::unsigned -> "column_3296")
+                projection ("test_space"."sysFrom"::unsigned -> "column_596", "test_space"."id"::unsigned -> "column_3396")
                     group by ("test_space"."sysFrom"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id")
                         scan "test_space"
 subquery $0:
@@ -2813,11 +2809,11 @@ fn front_sql_having_with_sq_segment_motion() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection ("column_596"::unsigned -> "sysFrom", "column_696"::unsigned -> "sys_op", sum(distinct ("column_3096"::decimal))::decimal -> "sum", count(distinct ("column_3096"::integer))::integer -> "count")
+        r#"projection ("column_596"::unsigned -> "sysFrom", "column_696"::unsigned -> "sys_op", sum(distinct ("column_3296"::decimal))::decimal -> "sum", count(distinct ("column_3296"::integer))::integer -> "count")
     having ROW("column_596"::unsigned, "column_696"::unsigned) in ROW($0, $0)
-        group by ("column_596"::unsigned, "column_696"::unsigned) output: ("column_596"::unsigned -> "column_596", "column_696"::unsigned -> "column_696", "column_3096"::unsigned -> "column_3096")
+        group by ("column_596"::unsigned, "column_696"::unsigned) output: ("column_596"::unsigned -> "column_596", "column_696"::unsigned -> "column_696", "column_3296"::unsigned -> "column_3296")
             motion [policy: segment([ref("column_596"), ref("column_696")])]
-                projection ("test_space"."sysFrom"::unsigned -> "column_596", "test_space"."sys_op"::unsigned -> "column_696", "test_space"."id"::unsigned -> "column_3096")
+                projection ("test_space"."sysFrom"::unsigned -> "column_596", "test_space"."sys_op"::unsigned -> "column_696", "test_space"."id"::unsigned -> "column_3296")
                     group by ("test_space"."sysFrom"::unsigned, "test_space"."sys_op"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id")
                         scan "test_space"
 subquery $0:
@@ -2848,11 +2844,11 @@ fn front_sql_having_with_sq_segment_local_motion() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection ("column_596"::unsigned -> "sysFrom", "column_696"::unsigned -> "sys_op", sum(distinct ("column_3096"::decimal))::decimal -> "sum", count(distinct ("column_3096"::integer))::integer -> "count")
+        r#"projection ("column_596"::unsigned -> "sysFrom", "column_696"::unsigned -> "sys_op", sum(distinct ("column_3296"::decimal))::decimal -> "sum", count(distinct ("column_3296"::integer))::integer -> "count")
     having ROW("column_596"::unsigned, "column_696"::unsigned) in ROW($0, $0)
-        group by ("column_596"::unsigned, "column_696"::unsigned) output: ("column_596"::unsigned -> "column_596", "column_696"::unsigned -> "column_696", "column_3096"::unsigned -> "column_3096")
+        group by ("column_596"::unsigned, "column_696"::unsigned) output: ("column_596"::unsigned -> "column_596", "column_696"::unsigned -> "column_696", "column_3296"::unsigned -> "column_3296")
             motion [policy: segment([ref("column_596"), ref("column_696")])]
-                projection ("test_space"."sysFrom"::unsigned -> "column_596", "test_space"."sys_op"::unsigned -> "column_696", "test_space"."id"::unsigned -> "column_3096")
+                projection ("test_space"."sysFrom"::unsigned -> "column_596", "test_space"."sys_op"::unsigned -> "column_696", "test_space"."id"::unsigned -> "column_3296")
                     group by ("test_space"."sysFrom"::unsigned, "test_space"."sys_op"::unsigned, "test_space"."id"::unsigned) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id")
                         scan "test_space"
 subquery $0:
@@ -3831,7 +3827,7 @@ fn front_subqueries_interpreted_as_expression() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection (ROW($0) -> "COL_1")
+        r#"projection (ROW($0) -> "col_1")
     scan "test_space"
 subquery $0:
 scan
@@ -3851,9 +3847,9 @@ fn front_subqueries_interpreted_as_expression_as_required_child() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection ("COL_1"::unsigned -> "COL_1")
+        r#"projection ("col_1"::unsigned -> "col_1")
     scan
-        projection (ROW($0) -> "COL_1")
+        projection (ROW($0) -> "col_1")
             scan "test_space"
 subquery $0:
 scan
@@ -3873,7 +3869,7 @@ fn front_subqueries_interpreted_as_expression_nested() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection (ROW($1) -> "COL_1")
+        r#"projection (ROW($1) -> "col_1")
     scan "test_space"
 subquery $0:
 scan
@@ -3897,21 +3893,20 @@ fn front_subqueries_interpreted_as_expression_under_group_by() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection (sum(("count_43"::integer))::decimal -> "COL_1")
-    group by ("column_29"::unsigned) output: ("column_29"::unsigned -> "column_29", "count_43"::integer -> "count_43")
-        motion [policy: segment([ref("column_29")])]
-            scan
-                projection (ROW("test_space"."id"::unsigned) + ROW($1) -> "column_29", count((*::integer))::integer -> "count_43")
-                    group by (ROW("test_space"."id"::unsigned) + ROW($0)) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id")
-                        scan "test_space"
+        r#"projection (sum(("count_1496"::integer))::decimal -> "col_1")
+    group by ("column_932"::unsigned) output: ("column_932"::unsigned -> "column_932", "count_1496"::integer -> "count_1496")
+        motion [policy: segment([ref("column_932")])]
+            projection (ROW("test_space"."id"::unsigned) + ROW($1) -> "column_932", count((*::integer))::integer -> "count_1496")
+                group by (ROW("test_space"."id"::unsigned) + ROW($0)) output: ("test_space"."id"::unsigned -> "id", "test_space"."sysFrom"::unsigned -> "sysFrom", "test_space"."FIRST_NAME"::string -> "FIRST_NAME", "test_space"."sys_op"::unsigned -> "sys_op", "test_space"."bucket_id"::unsigned -> "bucket_id")
+                    scan "test_space"
 subquery $0:
-scan
-                            values
-                                value row (data=ROW(1::unsigned))
-subquery $1:
 scan
                         values
                             value row (data=ROW(1::unsigned))
+subquery $1:
+scan
+                    values
+                        value row (data=ROW(1::unsigned))
 execution options:
 sql_vdbe_max_steps = 45000
 vtable_max_rows = 5000
diff --git a/sbroad-core/src/frontend/sql/ir/tests/global.rs b/sbroad-core/src/frontend/sql/ir/tests/global.rs
index bd71e1fcd5..c2717c59c7 100644
--- a/sbroad-core/src/frontend/sql/ir/tests/global.rs
+++ b/sbroad-core/src/frontend/sql/ir/tests/global.rs
@@ -118,18 +118,18 @@ fn front_sql_global_tbl_multiple_sqs1() {
     let plan = sql_to_optimized_ir(input, vec![]);
     let expected_explain = String::from(
         r#"projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b")
-    selection ROW("global_t"."a"::integer, "global_t"."b"::integer) in ROW($0, $0) and ROW("global_t"."a"::integer) in ROW($1)
+    selection ROW("global_t"."a"::integer, "global_t"."b"::integer) in ROW($1, $1) and ROW("global_t"."a"::integer) in ROW($0)
         scan "global_t"
 subquery $0:
-scan
-            projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1")
-                scan "t"
-subquery $1:
 scan
             projection (sum(("sum_1796"::decimal))::decimal -> "col_1")
                 motion [policy: full]
                     projection (sum(("t"."a"::unsigned))::decimal -> "sum_1796")
                         scan "t"
+subquery $1:
+scan
+            projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1")
+                scan "t"
 execution options:
 sql_vdbe_max_steps = 45000
 vtable_max_rows = 5000
@@ -155,19 +155,19 @@ fn front_sql_global_tbl_multiple_sqs2() {
     let plan = sql_to_optimized_ir(input, vec![]);
     let expected_explain = String::from(
         r#"projection ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b")
-    selection ROW("global_t"."a"::integer, "global_t"."b"::integer) in ROW($0, $0) or ROW("global_t"."a"::integer) in ROW($1)
+    selection ROW("global_t"."a"::integer, "global_t"."b"::integer) in ROW($1, $1) or ROW("global_t"."a"::integer) in ROW($0)
         scan "global_t"
 subquery $0:
-motion [policy: full]
-            scan
-                projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1")
-                    scan "t"
-subquery $1:
 scan
             projection (sum(("sum_1796"::decimal))::decimal -> "col_1")
                 motion [policy: full]
                     projection (sum(("t"."a"::unsigned))::decimal -> "sum_1796")
                         scan "t"
+subquery $1:
+motion [policy: full]
+            scan
+                projection ("t"."a"::unsigned -> "a1", "t"."b"::unsigned -> "b1")
+                    scan "t"
 execution options:
 sql_vdbe_max_steps = 45000
 vtable_max_rows = 5000
@@ -809,11 +809,11 @@ fn front_sql_global_aggregate5() {
     let plan = sql_to_optimized_ir(input, vec![]);
 
     let expected_explain = String::from(
-        r#"projection ("column_1432"::integer -> "col_1", sum(("sum_2696"::decimal))::decimal -> "col_2")
-    having ROW(sum(("sum_2096"::decimal::double))::decimal / sum(("count_2096"::decimal::double))::decimal) > ROW(3::unsigned)
-        group by ("column_1432"::integer) output: ("column_1432"::integer -> "column_1432", "sum_2696"::decimal -> "sum_2696", "sum_2096"::decimal -> "sum_2096", "count_2096"::integer -> "count_2096")
+        r#"projection ("column_1432"::integer -> "col_1", sum(("sum_2896"::decimal))::decimal -> "col_2")
+    having ROW(sum(("sum_2296"::decimal::double))::decimal / sum(("count_2296"::decimal::double))::decimal) > ROW(3::unsigned)
+        group by ("column_1432"::integer) output: ("column_1432"::integer -> "column_1432", "sum_2896"::decimal -> "sum_2896", "sum_2296"::decimal -> "sum_2296", "count_2296"::integer -> "count_2296")
             motion [policy: segment([ref("column_1432")])]
-                projection (ROW("global_t"."b"::integer) + ROW("global_t"."a"::integer) -> "column_1432", sum(("global_t"."a"::integer))::decimal -> "sum_2696", sum(("global_t"."b"::integer))::decimal -> "sum_2096", count(("global_t"."b"::integer))::integer -> "count_2096")
+                projection (ROW("global_t"."b"::integer) + ROW("global_t"."a"::integer) -> "column_1432", sum(("global_t"."a"::integer))::decimal -> "sum_2896", sum(("global_t"."b"::integer))::decimal -> "sum_2296", count(("global_t"."b"::integer))::integer -> "count_2296")
                     group by (ROW("global_t"."b"::integer) + ROW("global_t"."a"::integer)) output: ("global_t"."a"::integer -> "a", "global_t"."b"::integer -> "b")
                         selection ROW("global_t"."a"::integer, "global_t"."b"::integer) in ROW($0, $0)
                             scan "global_t"
diff --git a/sbroad-core/src/ir.rs b/sbroad-core/src/ir.rs
index 4b1ac4cf08..8ee56b3e24 100644
--- a/sbroad-core/src/ir.rs
+++ b/sbroad-core/src/ir.rs
@@ -1484,8 +1484,15 @@ impl Plan {
     ///
     /// # Errors
     /// - supplied id does not correspond to `Row` node
-    pub fn get_row_list(&self, row_id: usize) -> Result<&[usize], SbroadError> {
-        Ok(self.get_expression_node(row_id)?.get_row_list())
+    pub fn get_row_list(&self, row_id: NodeId) -> Result<&Vec<NodeId>, SbroadError> {
+        if let Expression::Row(Row { list, .. }) = self.get_expression_node(row_id)? {
+            return Ok(list);
+        }
+
+        Err(SbroadError::Invalid(
+            Entity::Expression,
+            Some("node is not Row".into()),
+        ))
     }
 
     /// Helper function to get id of node under alias node,
@@ -1760,7 +1767,7 @@ impl Plan {
         let column_expr_node = self.get_expression_node(column_rel_node.output())?;
 
         let col_alias_id = column_expr_node
-            .get_row_list()
+            .get_row_list()?
             .get(*position)
             .unwrap_or_else(|| panic!("Column not found at position {position} in row list"));
 
diff --git a/sbroad-core/src/ir/api/parameter.rs b/sbroad-core/src/ir/api/parameter.rs
index 9825c831bb..91b9902fd6 100644
--- a/sbroad-core/src/ir/api/parameter.rs
+++ b/sbroad-core/src/ir/api/parameter.rs
@@ -635,9 +635,9 @@ impl Plan {
                 panic!("Expected a values row: {values_row:?}")
             };
         let data = self.get_expression_node(data_id)?;
-        let data_list = data.clone_row_list();
+        let data_list = data.clone_row_list()?;
         let output = self.get_expression_node(output_id)?;
-        let output_list = output.clone_row_list();
+        let output_list = output.clone_row_list()?;
         for (pos, alias_id) in output_list.iter().enumerate() {
             let new_child_id = *data_list
                 .get(pos)
diff --git a/sbroad-core/src/ir/distribution.rs b/sbroad-core/src/ir/distribution.rs
index 8f637a7ca6..1e9aec1392 100644
--- a/sbroad-core/src/ir/distribution.rs
+++ b/sbroad-core/src/ir/distribution.rs
@@ -413,7 +413,7 @@ impl From<(NodeId, usize)> for ChildColumnReference {
 impl Plan {
     /// Sets distribution for output tuple of projection.
     /// Applied in case two stage aggregation is not present.
-    pub fn set_projection_distribution(&mut self, proj_id: usize) -> Result<(), SbroadError> {
+    pub fn set_projection_distribution(&mut self, proj_id: NodeId) -> Result<(), SbroadError> {
         if !matches!(
             self.get_relation_node(proj_id)?,
             Relational::Projection { .. }
@@ -619,10 +619,10 @@ impl Plan {
     ) -> Result<Distribution, SbroadError> {
         let rel_node = self.get_relation_node(child_rel_node)?;
         let output_expr = self.get_expression_node(rel_node.output())?;
-        if let Expression::Row {
+        if let Expression::Row(Row {
             distribution: child_dist,
             ..
-        } = output_expr
+        }) = output_expr
         {
             match child_dist {
                 None => panic!("Unable to calculate distribution from child: it's uninitialized."),
@@ -675,7 +675,7 @@ impl Plan {
     ///
     /// # Panics
     /// - Supplied node is `Row`.
-    pub fn set_dist(&mut self, row_id: usize, dist: Distribution) -> Result<(), SbroadError> {
+    pub fn set_dist(&mut self, row_id: NodeId, dist: Distribution) -> Result<(), SbroadError> {
         if let MutExpression::Row(Row {
             ref mut distribution,
             ..
@@ -736,9 +736,8 @@ impl Plan {
     ///
     /// # Errors
     /// - Node is not of a row type.
-    pub fn get_distribution(&self, row_id: usize) -> Result<&Distribution, SbroadError> {
-        let expr = self.get_expression_node(row_id)?;
-        Ok(expr.distribution())
+    pub fn get_distribution(&self, row_id: NodeId) -> Result<&Distribution, SbroadError> {
+        self.distribution(row_id)
     }
 
     /// Gets distribution of the relational node.
diff --git a/sbroad-core/src/ir/explain.rs b/sbroad-core/src/ir/explain.rs
index c8bd504fba..6a945fcb7f 100644
--- a/sbroad-core/src/ir/explain.rs
+++ b/sbroad-core/src/ir/explain.rs
@@ -11,17 +11,16 @@ use crate::executor::engine::helpers::to_user;
 use crate::ir::expression::cast::Type as CastType;
 use crate::ir::expression::TrimKind;
 use crate::ir::node::{
-    Alias, ArithmeticExpr, BoolExpr, Case, Cast, Constant, Delete, GroupBy as GroupByRel, Having,
-    Insert, Join, Motion as MotionRel, NodeId, OrderBy as OrderByRel, Projection as ProjectionRel,
-    Reference, Row as RowExpr, ScanCte, ScanRelation, ScanSubQuery, Selection, StableFunction,
-    Trim, UnaryExpr, Update as UpdateRel, Values, ValuesRow,
+    Alias, ArithmeticExpr, BoolExpr, Case, Cast, Constant, Delete, Having, Insert, Join,
+    Motion as MotionRel, NodeId, Reference, Row as RowExpr, ScanCte, ScanRelation, ScanSubQuery,
+    Selection, StableFunction, Trim, UnaryExpr, Update as UpdateRel, Values, ValuesRow,
 };
 use crate::ir::operator::{ConflictStrategy, JoinKind, OrderByElement, OrderByEntity, OrderByType};
 use crate::ir::relation::Type;
 use crate::ir::transformation::redistribution::{
     MotionKey as IrMotionKey, MotionPolicy as IrMotionPolicy, Target as IrTarget,
 };
-use crate::ir::{OptionKind, Plan};
+use crate::ir::{node, OptionKind, Plan};
 
 use super::expression::FunctionFeature;
 use super::node::expression::Expression;
@@ -386,7 +385,7 @@ impl Projection {
 
         let alias_list = plan.get_expression_node(output_id)?;
 
-        for col_node_id in alias_list.get_row_list() {
+        for col_node_id in alias_list.get_row_list()? {
             let col = ColExpr::new(plan, *col_node_id, sq_ref_map)?;
 
             result.cols.push(col);
@@ -436,7 +435,7 @@ impl GroupBy {
             result.gr_cols.push(col);
         }
         let alias_list = plan.get_expression_node(output_id)?;
-        for col_node_id in alias_list.get_row_list() {
+        for col_node_id in alias_list.get_row_list()? {
             let col = ColExpr::new(plan, *col_node_id, sq_ref_map)?;
             result.output_cols.push(col);
         }
@@ -1045,7 +1044,7 @@ impl FullExplain {
             let mut current_node = ExplainTreePart::with_level(level);
             let node = ir.get_relation_node(id)?;
 
-            let mut get_sq_ref_map = |children: &Vec<usize>, req_children_number| {
+            let mut get_sq_ref_map = |children: &Vec<NodeId>, req_children_number| {
                 let mut sq_ref_map: SubQueryRefMap = HashMap::with_capacity(children.len());
 
                 // Note that subqueries are added to the stack in the `children` reveresed order
@@ -1096,7 +1095,7 @@ impl FullExplain {
                     }
                     Some(ExplainNode::Except)
                 }
-                Relational::GroupBy(GroupBy {
+                Relational::GroupBy(node::GroupBy {
                     gr_cols,
                     output,
                     children,
@@ -1106,7 +1105,7 @@ impl FullExplain {
                     let p = GroupBy::new(ir, gr_cols, *output, &sq_ref_map)?;
                     Some(ExplainNode::GroupBy(p))
                 }
-                Relational::OrderBy(OrderBy {
+                Relational::OrderBy(node::OrderBy {
                     order_by_elements,
                     children,
                     ..
@@ -1115,7 +1114,7 @@ impl FullExplain {
                     let o_b = OrderBy::new(ir, order_by_elements, &sq_ref_map)?;
                     Some(ExplainNode::OrderBy(o_b))
                 }
-                Relational::Projection(Projection {
+                Relational::Projection(node::Projection {
                     output, children, ..
                 }) => {
                     let sq_ref_map = get_sq_ref_map(children, 1);
@@ -1145,7 +1144,7 @@ impl FullExplain {
                 })
                 | Relational::Having(Having {
                     children, filter, ..
-                } => {
+                }) => {
                     let sq_ref_map = get_sq_ref_map(children, 1);
                     let filter_id = ir.undo.get_oldest(filter).map_or_else(|| *filter, |id| *id);
                     let selection = ColExpr::new(ir, filter_id, &sq_ref_map)?;
@@ -1199,7 +1198,7 @@ impl FullExplain {
                         })?;
 
                         let child_output_id = ir.get_relation_node(*child_id)?.output();
-                        let col_list = ir.get_expression_node(child_output_id)?.get_row_list();
+                        let col_list = ir.get_row_list(child_output_id)?;
 
                         let targets = (s.targets)
                             .iter()
@@ -1254,7 +1253,7 @@ impl FullExplain {
                         kind: kind.clone(),
                     }))
                 }
-                Relational::ValuesRow { data, children, .. } => {
+                Relational::ValuesRow(ValuesRow { data, children, .. }) => {
                     let sq_ref_map = get_sq_ref_map(children, 0);
                     let row = ColExpr::new(ir, *data, &sq_ref_map)?;
 
diff --git a/sbroad-core/src/ir/expression.rs b/sbroad-core/src/ir/expression.rs
index 0e8dfec475..2b18a20f8f 100644
--- a/sbroad-core/src/ir/expression.rs
+++ b/sbroad-core/src/ir/expression.rs
@@ -648,7 +648,7 @@ impl ColumnPositionMap {
     pub(crate) fn new(plan: &Plan, rel_id: NodeId) -> Result<Self, SbroadError> {
         let rel_node = plan.get_relation_node(rel_id)?;
         let output = plan.get_expression_node(rel_node.output())?;
-        let alias_ids = output.get_row_list();
+        let alias_ids = output.get_row_list()?;
 
         let mut map = BTreeMap::new();
         let mut max_name = None;
@@ -1442,7 +1442,7 @@ impl Plan {
     }
 
     /// The node is a trivalent (boolean or NULL).
-    pub fn is_trivalent(&self, expr_id: usize) -> Result<bool, SbroadError> {
+    pub fn is_trivalent(&self, expr_id: NodeId) -> Result<bool, SbroadError> {
         let expr_node = self.get_node(expr_id)?;
         let expr = match expr_node {
             Node::Parameter(_) => return Ok(true),
@@ -1465,7 +1465,9 @@ impl Plan {
                     return self.is_trivalent(*inner_id);
                 }
             }
-            Expression::Reference { col_type, .. } => return Ok(matches!(col_type, Type::Boolean)),
+            Expression::Reference(Reference { col_type, .. }) => {
+                return Ok(matches!(col_type, Type::Boolean))
+            }
             _ => {}
         }
         Ok(false)
diff --git a/sbroad-core/src/ir/helpers.rs b/sbroad-core/src/ir/helpers.rs
index 0aba62ca17..3750ddde17 100644
--- a/sbroad-core/src/ir/helpers.rs
+++ b/sbroad-core/src/ir/helpers.rs
@@ -226,49 +226,39 @@ impl Plan {
             writeln!(buf, "---------------------------------------------")?;
         }
         write_with_tabulation(buf, tabulation_number, format!("[id: {node_id}] ").as_str())?;
-        let relation = self.get_relation_node(node_id);
-        if let Ok(relation) = relation {
-            write!(buf, "relation: ")?;
-            // Print relation name and specific info.
-            match relation {
-                Relational::ScanRelation(ScanRelation {
-                    alias, relation, ..
-                }) => {
-                    writeln!(buf, "ScanRelation")?;
-                    writeln_with_tabulation(
-                        buf,
-                        tabulation_number + 1,
-                        format!("Relation: {relation}").as_str(),
-                    )?;
-                    if let Some(alias) = alias {
+        let node = self.get_node(node_id).expect("Plan must be valid");
+        match node {
+            Node::Relational(relation) => {
+                write!(buf, "relation: ")?;
+                // Print relation name and specific info.
+                match relation {
+                    Relational::ScanRelation(ScanRelation {
+                        alias, relation, ..
+                    }) => {
+                        writeln!(buf, "ScanRelation")?;
                         writeln_with_tabulation(
                             buf,
                             tabulation_number + 1,
-                            format!("Alias: {alias}").as_str(),
+                            format!("Relation: {relation}").as_str(),
                         )?;
+                        if let Some(alias) = alias {
+                            writeln_with_tabulation(
+                                buf,
+                                tabulation_number + 1,
+                                format!("Alias: {alias}").as_str(),
+                            )?;
+                        }
                     }
-                }
-                Relational::Join(Join { condition, .. }) => {
-                    writeln!(buf, "InnerJoin")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Condition:")?;
-                    self.formatted_arena_node(buf, tabulation_number + 2, *condition)?;
-                }
-                Relational::Projection(_) => {
-                    writeln!(buf, "Projection")?;
-                }
-                Relational::ScanCte(ScanCte { alias, .. }) => {
-                    writeln!(buf, "ScanCte")?;
-                    if !alias.is_empty() {
-                        writeln_with_tabulation(
-                            buf,
-                            tabulation_number + 1,
-                            format!("Alias: {alias}").as_str(),
-                        )?;
+                    Relational::Join(Join { condition, .. }) => {
+                        writeln!(buf, "InnerJoin")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Condition:")?;
+                        self.formatted_arena_node(buf, tabulation_number + 2, *condition)?;
                     }
-                }
-                Relational::ScanSubQuery(ScanSubQuery { alias, .. }) => {
-                    writeln!(buf, "ScanSubQuery")?;
-                    if let Some(alias) = alias {
+                    Relational::Projection(_) => {
+                        writeln!(buf, "Projection")?;
+                    }
+                    Relational::ScanCte(ScanCte { alias, .. }) => {
+                        writeln!(buf, "ScanCte")?;
                         if !alias.is_empty() {
                             writeln_with_tabulation(
                                 buf,
@@ -277,165 +267,183 @@ impl Plan {
                             )?;
                         }
                     }
-                }
-                Relational::Selection(Selection {
-                    children: _,
-                    filter,
-                    output: _,
-                }) => {
-                    writeln!(buf, "Selection")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Filter")?;
-                    self.formatted_arena_node(buf, tabulation_number + 1, *filter)?;
-                }
-                Relational::Having(Having { filter, .. }) => {
-                    writeln!(buf, "Having")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Filter")?;
-                    self.formatted_arena_node(buf, tabulation_number + 1, *filter)?;
-                }
-                Relational::GroupBy(GroupBy {
-                    gr_cols, is_final, ..
-                }) => {
-                    writeln!(buf, "GroupBy [is_final = {is_final}]")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Gr_cols:")?;
-                    for gr_col in gr_cols {
-                        let gl_col_expr = self.get_expression_node(*gr_col);
-                        let text = if let Ok(gl_col_expr) = gl_col_expr {
-                            format!("Gr_col: {gl_col_expr:?}")
-                        } else {
-                            format!("Gr_col: {gr_col}")
-                        };
-                        writeln_with_tabulation(buf, tabulation_number + 2, text.as_str())?;
+                    Relational::ScanSubQuery(ScanSubQuery { alias, .. }) => {
+                        writeln!(buf, "ScanSubQuery")?;
+                        if let Some(alias) = alias {
+                            if !alias.is_empty() {
+                                writeln_with_tabulation(
+                                    buf,
+                                    tabulation_number + 1,
+                                    format!("Alias: {alias}").as_str(),
+                                )?;
+                            }
+                        }
                     }
-                }
-                Relational::OrderBy(OrderBy {
-                    order_by_elements, ..
-                }) => {
-                    writeln!(buf, "OrderBy")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Order_by_elements:")?;
-                    for element in order_by_elements {
-                        let order_by_entity_str = match element.entity {
-                            OrderByEntity::Expression { expr_id } => {
-                                let order_by_expr = self.get_expression_node(expr_id);
-                                if let Ok(order_by_expr) = order_by_expr {
-                                    format!("{order_by_expr:?}")
-                                } else {
-                                    "?".to_string()
+                    Relational::Selection(Selection {
+                        children: _,
+                        filter,
+                        output: _,
+                    }) => {
+                        writeln!(buf, "Selection")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Filter")?;
+                        self.formatted_arena_node(buf, tabulation_number + 1, *filter)?;
+                    }
+                    Relational::Having(Having { filter, .. }) => {
+                        writeln!(buf, "Having")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Filter")?;
+                        self.formatted_arena_node(buf, tabulation_number + 1, *filter)?;
+                    }
+                    Relational::GroupBy(GroupBy {
+                        gr_cols, is_final, ..
+                    }) => {
+                        writeln!(buf, "GroupBy [is_final = {is_final}]")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Gr_cols:")?;
+                        for gr_col in gr_cols {
+                            let gl_col_expr = self.get_expression_node(*gr_col);
+                            let text = if let Ok(gl_col_expr) = gl_col_expr {
+                                format!("Gr_col: {gl_col_expr:?}")
+                            } else {
+                                format!("Gr_col: {gr_col}")
+                            };
+                            writeln_with_tabulation(buf, tabulation_number + 2, text.as_str())?;
+                        }
+                    }
+                    Relational::OrderBy(OrderBy {
+                        order_by_elements, ..
+                    }) => {
+                        writeln!(buf, "OrderBy")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Order_by_elements:")?;
+                        for element in order_by_elements {
+                            let order_by_entity_str = match element.entity {
+                                OrderByEntity::Expression { expr_id } => {
+                                    let order_by_expr = self.get_expression_node(expr_id);
+                                    if let Ok(order_by_expr) = order_by_expr {
+                                        format!("{order_by_expr:?}")
+                                    } else {
+                                        "?".to_string()
+                                    }
                                 }
-                            }
-                            OrderByEntity::Index { value } => format!("{value}"),
-                        };
-                        let order_by_type = element.order_type.clone();
-                        writeln_with_tabulation(buf, tabulation_number + 2, format!("Order_by_element: {order_by_entity_str} [order_type = {order_by_type:?}]").as_str())?;
+                                OrderByEntity::Index { value } => format!("{value}"),
+                            };
+                            let order_by_type = element.order_type.clone();
+                            writeln_with_tabulation(buf, tabulation_number + 2, format!("Order_by_element: {order_by_entity_str} [order_type = {order_by_type:?}]").as_str())?;
+                        }
                     }
-                }
-                Relational::Values { .. } => writeln!(buf, "Values")?,
-                Relational::ValuesRow(ValuesRow { data, .. }) => {
-                    writeln!(buf, "ValuesRow")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Data")?;
-                    self.formatted_arena_node(buf, tabulation_number + 1, *data)?;
-                }
-                Relational::Motion(Motion { policy, alias, .. }) => {
-                    write!(buf, "Motion [policy = {policy:?}, alias = ")?;
-                    if let Some(alias) = alias {
-                        write!(buf, "{alias}")?;
-                    } else {
-                        write!(buf, "None")?;
+                    Relational::Values { .. } => writeln!(buf, "Values")?,
+                    Relational::ValuesRow(ValuesRow { data, .. }) => {
+                        writeln!(buf, "ValuesRow")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Data")?;
+                        self.formatted_arena_node(buf, tabulation_number + 1, *data)?;
                     }
-                    writeln!(buf, "]")?;
-                }
-                Relational::Union { .. } => writeln!(buf, "Union")?,
-                Relational::UnionAll { .. } => writeln!(buf, "UnionAll")?,
-                Relational::Update(Update {
-                    relation,
-                    update_columns_map,
-                    ..
-                }) => {
-                    writeln!(buf, "Update")?;
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Update columns map:")?;
-                    for (rel_pos, proj_pos) in update_columns_map {
-                        writeln_with_tabulation(buf, tabulation_number + 2, format!("Update {relation} column on pos {rel_pos} to child projection column on pos {proj_pos}").as_str())?;
+                    Relational::Motion(Motion { policy, alias, .. }) => {
+                        write!(buf, "Motion [policy = {policy:?}, alias = ")?;
+                        if let Some(alias) = alias {
+                            write!(buf, "{alias}")?;
+                        } else {
+                            write!(buf, "None")?;
+                        }
+                        writeln!(buf, "]")?;
+                    }
+                    Relational::Union { .. } => writeln!(buf, "Union")?,
+                    Relational::UnionAll { .. } => writeln!(buf, "UnionAll")?,
+                    Relational::Update(Update {
+                        relation,
+                        update_columns_map,
+                        ..
+                    }) => {
+                        writeln!(buf, "Update")?;
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Update columns map:")?;
+                        for (rel_pos, proj_pos) in update_columns_map {
+                            writeln_with_tabulation(buf, tabulation_number + 2, format!("Update {relation} column on pos {rel_pos} to child projection column on pos {proj_pos}").as_str())?;
+                        }
                     }
+                    Relational::Delete(_) => writeln!(buf, "Delete")?,
+                    Relational::Insert(_) => writeln!(buf, "Insert")?,
+                    Relational::Intersect(_) => writeln!(buf, "Intersect")?,
+                    Relational::Except(_) => writeln!(buf, "Except")?,
+                    Relational::Limit(Limit { limit, .. }) => writeln!(buf, "Limit {limit}")?,
                 }
-                Relational::Delete(_) => writeln!(buf, "Delete")?,
-                Relational::Insert(_) => writeln!(buf, "Insert")?,
-                Relational::Intersect(_) => writeln!(buf, "Intersect")?,
-                Relational::Except(_) => writeln!(buf, "Except")?,
-                Relational::Limit(Limit { limit, .. }) => writeln!(buf, "Limit {limit}")?,
-            }
-            // Print children.
-            match relation {
-                Relational::Join(_)
-                | Relational::Projection(_)
-                | Relational::Except(_)
-                | Relational::Delete(_)
-                | Relational::Insert(_)
-                | Relational::Intersect(_)
-                | Relational::ScanSubQuery(_)
-                | Relational::Selection(_)
-                | Relational::Values(_)
-                | Relational::OrderBy(_)
-                | Relational::Limit(_)
-                | Relational::Motion(_)
-                | Relational::Union(_)
-                | Relational::UnionAll(_)
-                | Relational::Update(_)
-                | Relational::Having(_)
-                | Relational::GroupBy(_)
-                | Relational::ValuesRow(_) => {
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Children:")?;
-                    for child in &relation.children() {
+                // Print children.
+                match relation {
+                    Relational::Join(_)
+                    | Relational::Projection(_)
+                    | Relational::Except(_)
+                    | Relational::Delete(_)
+                    | Relational::Insert(_)
+                    | Relational::Intersect(_)
+                    | Relational::ScanSubQuery(_)
+                    | Relational::Selection(_)
+                    | Relational::Values(_)
+                    | Relational::OrderBy(_)
+                    | Relational::Limit(_)
+                    | Relational::Motion(_)
+                    | Relational::Union(_)
+                    | Relational::UnionAll(_)
+                    | Relational::Update(_)
+                    | Relational::Having(_)
+                    | Relational::GroupBy(_)
+                    | Relational::ValuesRow(_) => {
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Children:")?;
+                        for child in &relation.children() {
+                            writeln_with_tabulation(
+                                buf,
+                                tabulation_number + 2,
+                                format!("Child_id = {child}").as_str(),
+                            )?;
+                        }
+                    }
+                    Relational::ScanCte(ScanCte { child, .. }) => {
+                        writeln_with_tabulation(buf, tabulation_number + 1, "Children:")?;
                         writeln_with_tabulation(
                             buf,
                             tabulation_number + 2,
                             format!("Child_id = {child}").as_str(),
                         )?;
                     }
+                    Relational::ScanRelation { .. } => {
+                        writeln_with_tabulation(buf, tabulation_number + 1, "[No children]")?;
+                    }
                 }
-                Relational::ScanCte(ScanCte { child, .. }) => {
-                    writeln_with_tabulation(buf, tabulation_number + 1, "Children:")?;
-                    writeln_with_tabulation(
-                        buf,
-                        tabulation_number + 2,
-                        format!("Child_id = {child}").as_str(),
-                    )?;
-                }
-                Relational::ScanRelation { .. } => {
-                    writeln_with_tabulation(buf, tabulation_number + 1, "[No children]")?;
+                // Print output.
+                match relation {
+                    Relational::ScanRelation(ScanRelation { output, .. })
+                    | Relational::Join(Join { output, .. })
+                    | Relational::Except(Except { output, .. })
+                    | Relational::Delete(Delete { output, .. })
+                    | Relational::Insert(Insert { output, .. })
+                    | Relational::Intersect(Intersect { output, .. })
+                    | Relational::Projection(Projection { output, .. })
+                    | Relational::ScanCte(ScanCte { output, .. })
+                    | Relational::ScanSubQuery(ScanSubQuery { output, .. })
+                    | Relational::GroupBy(GroupBy { output, .. })
+                    | Relational::OrderBy(OrderBy { output, .. })
+                    | Relational::Selection(Selection { output, .. })
+                    | Relational::Having(Having { output, .. })
+                    | Relational::Values(Values { output, .. })
+                    | Relational::Motion(Motion { output, .. })
+                    | Relational::Union(Union { output, .. })
+                    | Relational::UnionAll(UnionAll { output, .. })
+                    | Relational::Update(Update { output, .. })
+                    | Relational::ValuesRow(ValuesRow { output, .. })
+                    | Relational::Limit(Limit { output, .. }) => {
+                        writeln_with_tabulation(
+                            buf,
+                            tabulation_number + 1,
+                            format!("Output_id: {output}").as_str(),
+                        )?;
+                        self.formatted_arena_node(buf, tabulation_number + 2, *output)?;
+                    }
                 }
+                writeln!(buf, "---------------------------------------------")?;
             }
-            // Print output.
-            match relation {
-                Relational::ScanRelation(ScanRelation { output, .. })
-                | Relational::Join(Join { output, .. })
-                | Relational::Except(Except { output, .. })
-                | Relational::Delete(Delete { output, .. })
-                | Relational::Insert(Insert { output, .. })
-                | Relational::Intersect(Intersect { output, .. })
-                | Relational::Projection(Projection { output, .. })
-                | Relational::ScanCte(ScanCte { output, .. })
-                | Relational::ScanSubQuery(ScanSubQuery { output, .. })
-                | Relational::GroupBy(GroupBy { output, .. })
-                | Relational::OrderBy(OrderBy { output, .. })
-                | Relational::Selection(Selection { output, .. })
-                | Relational::Having(Having { output, .. })
-                | Relational::Values(Values { output, .. })
-                | Relational::Motion(Motion { output, .. })
-                | Relational::Union(Union { output, .. })
-                | Relational::UnionAll(UnionAll { output, .. })
-                | Relational::Update(Update { output, .. })
-                | Relational::ValuesRow(ValuesRow { output, .. })
-                | Relational::Limit(Limit { output, .. }) => {
-                    writeln_with_tabulation(
-                        buf,
-                        tabulation_number + 1,
-                        format!("Output_id: {output}").as_str(),
-                    )?;
-                    self.formatted_arena_node(buf, tabulation_number + 2, *output)?;
-                }
+            Node::Expression(_) => {
+                self.write_expr(buf, tabulation_number, node_id)?;
             }
-            writeln!(buf, "---------------------------------------------")?;
-        } else {
-            self.write_expr(buf, tabulation_number, node_id)?;
+            Node::Invalid(_) => {
+                writeln!(buf, "INVALID")?;
+                writeln!(buf, "---------------------------------------------")?;
+            }
+            _ => {}
         }
         Ok(())
     }
diff --git a/sbroad-core/src/ir/node.rs b/sbroad-core/src/ir/node.rs
index cd3ddf822e..c1c77191f3 100644
--- a/sbroad-core/src/ir/node.rs
+++ b/sbroad-core/src/ir/node.rs
@@ -646,7 +646,7 @@ impl From<Having> for NodeAligned {
 
 #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct OrderBy {
-    pub child: NodeId,
+    pub children: Vec<NodeId>,
     pub output: NodeId,
     pub order_by_elements: Vec<OrderByElement>,
 }
diff --git a/sbroad-core/src/ir/node/expression.rs b/sbroad-core/src/ir/node/expression.rs
index b915549152..e9d3738457 100644
--- a/sbroad-core/src/ir/node/expression.rs
+++ b/sbroad-core/src/ir/node/expression.rs
@@ -149,15 +149,6 @@ impl Expression<'_> {
         }
     }
 
-    /// Checks for distribution determination
-    ///
-    /// # Errors
-    /// - distribution isn't set
-    pub fn has_unknown_distribution(&self) -> Result<bool, SbroadError> {
-        let d = self.distribution()?;
-        Ok(d.is_unknown())
-    }
-
     /// Gets relational node id containing the reference.
     ///
     /// # Errors
diff --git a/sbroad-core/src/ir/node/relational.rs b/sbroad-core/src/ir/node/relational.rs
index 2f0efdc9ca..0148644397 100644
--- a/sbroad-core/src/ir/node/relational.rs
+++ b/sbroad-core/src/ir/node/relational.rs
@@ -115,6 +115,10 @@ impl RelOwned {
                 children: ref mut old,
                 ..
             })
+            | RelOwned::OrderBy(OrderBy {
+                children: ref mut old,
+                ..
+            })
             | RelOwned::ValuesRow(ValuesRow {
                 children: ref mut old,
                 ..
@@ -131,13 +135,6 @@ impl RelOwned {
                 *left = children[0];
                 *right = children[1];
             }
-            RelOwned::OrderBy(OrderBy { ref mut child, .. }) => {
-                if children.len() != 1 {
-                    unreachable!("ORDER BY may have only a single relational child");
-                }
-                // It is safe to unwrap here, because the length is already checked above.
-                *child = children[0];
-            }
             RelOwned::ScanCte(ScanCte { ref mut child, .. }) => {
                 if children.len() != 1 {
                     unreachable!("CTE may have only a single relational child");
@@ -162,9 +159,9 @@ impl RelOwned {
     #[must_use]
     pub fn children(&self) -> Children<'_> {
         match self {
-            RelOwned::Limit(Limit { child, .. })
-            | RelOwned::OrderBy(OrderBy { child, .. })
-            | RelOwned::ScanCte(ScanCte { child, .. }) => Children::Single(child),
+            RelOwned::Limit(Limit { child, .. }) | RelOwned::ScanCte(ScanCte { child, .. }) => {
+                Children::Single(child)
+            }
             RelOwned::Except(Except { left, right, .. })
             | RelOwned::Intersect(Intersect { left, right, .. })
             | RelOwned::UnionAll(UnionAll { left, right, .. })
@@ -173,6 +170,7 @@ impl RelOwned {
             | RelOwned::Update(Update { children, .. })
             | RelOwned::Join(Join { children, .. })
             | RelOwned::Having(Having { children, .. })
+            | RelOwned::OrderBy(OrderBy { children, .. })
             | RelOwned::Delete(Delete { children, .. })
             | RelOwned::Insert(Insert { children, .. })
             | RelOwned::Motion(Motion { children, .. })
@@ -189,7 +187,6 @@ impl RelOwned {
     pub fn mut_children(&mut self) -> MutChildren<'_> {
         match self {
             RelOwned::Limit(Limit { ref mut child, .. })
-            | RelOwned::OrderBy(OrderBy { ref mut child, .. })
             | RelOwned::ScanCte(ScanCte { ref mut child, .. }) => MutChildren::Single(child),
             RelOwned::Except(Except {
                 ref mut left,
@@ -220,6 +217,9 @@ impl RelOwned {
             | RelOwned::Join(Join {
                 ref mut children, ..
             })
+            | RelOwned::OrderBy(OrderBy {
+                ref mut children, ..
+            })
             | RelOwned::Having(Having {
                 ref mut children, ..
             })
@@ -367,7 +367,6 @@ impl MutRelational<'_> {
         // return MutChildren { node: self };
         match self {
             MutRelational::Limit(Limit { child, .. })
-            | MutRelational::OrderBy(OrderBy { child, .. })
             | MutRelational::ScanCte(ScanCte { child, .. }) => MutChildren::Single(child),
             MutRelational::Except(Except { left, right, .. })
             | MutRelational::Intersect(Intersect { left, right, .. })
@@ -379,6 +378,9 @@ impl MutRelational<'_> {
             | MutRelational::Update(Update {
                 ref mut children, ..
             })
+            | MutRelational::OrderBy(OrderBy {
+                ref mut children, ..
+            })
             | MutRelational::Having(Having {
                 ref mut children, ..
             })
@@ -463,6 +465,10 @@ impl MutRelational<'_> {
                 children: ref mut old,
                 ..
             })
+            | MutRelational::OrderBy(OrderBy {
+                children: ref mut old,
+                ..
+            })
             | MutRelational::ValuesRow(ValuesRow {
                 children: ref mut old,
                 ..
@@ -479,13 +485,6 @@ impl MutRelational<'_> {
                 *left = children[0];
                 *right = children[1];
             }
-            MutRelational::OrderBy(OrderBy { ref mut child, .. }) => {
-                if children.len() != 1 {
-                    unreachable!("ORDER BY may have only a single relational child");
-                }
-                // It is safe to unwrap here, because the length is already checked above.
-                *child = children[0];
-            }
             MutRelational::ScanCte(ScanCte { ref mut child, .. }) => {
                 if children.len() != 1 {
                     unreachable!("CTE may have only a single relational child");
@@ -506,6 +505,24 @@ impl MutRelational<'_> {
         }
     }
 
+    /// Add `SubQuery` to the list of relational children.
+    ///
+    /// # Panics
+    /// - Trying to add subquery to inapplicable relational node.
+    pub fn add_sq_child(&mut self, sq_id: NodeId) {
+        match self {
+            MutRelational::Join(Join { children, .. })
+            | MutRelational::Projection(Projection { children, .. })
+            | MutRelational::Selection(Selection { children, .. })
+            | MutRelational::GroupBy(GroupBy { children, .. })
+            | MutRelational::Having(Having { children, .. })
+            | MutRelational::OrderBy(OrderBy { children, .. })
+            | MutRelational::Update(Update { children, .. })
+            | MutRelational::ValuesRow(ValuesRow { children, .. }) => children.push(sq_id),
+            _ => panic!("Unable to add SubQuery child to {self:?}."),
+        }
+    }
+
     /// Sets new scan name to relational node.
     ///
     /// # Errors
@@ -566,9 +583,9 @@ impl Relational<'_> {
     #[must_use]
     pub fn children(&self) -> Children<'_> {
         match self {
-            Relational::Limit(Limit { child, .. })
-            | Relational::OrderBy(OrderBy { child, .. })
-            | Relational::ScanCte(ScanCte { child, .. }) => Children::Single(child),
+            Relational::Limit(Limit { child, .. }) | Relational::ScanCte(ScanCte { child, .. }) => {
+                Children::Single(child)
+            }
             Relational::Except(Except { left, right, .. })
             | Relational::Intersect(Intersect { left, right, .. })
             | Relational::UnionAll(UnionAll { left, right, .. })
@@ -576,6 +593,7 @@ impl Relational<'_> {
             Relational::GroupBy(GroupBy { children, .. })
             | Relational::Update(Update { children, .. })
             | Relational::Join(Join { children, .. })
+            | Relational::OrderBy(OrderBy { children, .. })
             | Relational::Having(Having { children, .. })
             | Relational::Delete(Delete { children, .. })
             | Relational::Insert(Insert { children, .. })
diff --git a/sbroad-core/src/ir/operator.rs b/sbroad-core/src/ir/operator.rs
index 85a030fcb2..073b75f2bb 100644
--- a/sbroad-core/src/ir/operator.rs
+++ b/sbroad-core/src/ir/operator.rs
@@ -7,9 +7,9 @@ use crate::frontend::sql::get_unnamed_column_alias;
 use crate::ir::api::children::Children;
 use crate::ir::expression::PlanExpr;
 use crate::ir::node::{
-    Alias, Delete, Except, GroupBy, Having, Insert, Intersect, Join, Motion, MutNode, Node64,
-    NodeId, OrderBy, Projection, Reference, Row, ScanCte, ScanRelation, ScanSubQuery, Selection,
-    Union, UnionAll, Update, Values, ValuesRow,
+    Alias, Delete, Except, GroupBy, Having, Insert, Intersect, Join, Motion, MutNode, NodeId,
+    OrderBy, Projection, Reference, Row, ScanCte, ScanRelation, ScanSubQuery, Selection, Union,
+    UnionAll, Update, Values, ValuesRow,
 };
 use crate::ir::Plan;
 use ahash::RandomState;
@@ -357,7 +357,10 @@ impl Plan {
     pub fn add_except(&mut self, left: NodeId, right: NodeId) -> Result<NodeId, SbroadError> {
         let child_row_len = |child: NodeId, plan: &Plan| -> Result<usize, SbroadError> {
             let child_output = plan.get_relation_node(child)?.output();
-            Ok(plan.get_expression_node(child_output)?.get_row_list().len())
+            Ok(plan
+                .get_expression_node(child_output)?
+                .get_row_list()?
+                .len())
         };
 
         let left_row_len = child_row_len(left, self)?;
@@ -718,9 +721,7 @@ impl Plan {
 
         let mut refs: Vec<NodeId> = Vec::with_capacity(rel.columns.len());
         for (pos, col) in rel.columns.iter().enumerate() {
-            let r_id = self
-                .nodes
-                .add_ref(None, None, pos, col.r#type, None);
+            let r_id = self.nodes.add_ref(None, None, pos, col.r#type, None);
             let col_alias_id = self.nodes.add_alias(&col.name, r_id)?;
             refs.push(col_alias_id);
         }
@@ -1203,7 +1204,7 @@ impl Plan {
             let child_columns = self
                 .get_expression_node(child_output_id)
                 .expect("output row")
-                .clone_row_list();
+                .clone_row_list()?;
             if child_columns.len() != columns.len() {
                 return Err(SbroadError::UnexpectedNumberOfValues(format_smolstr!(
                     "expected {} columns in CTE, got {}",
@@ -1249,7 +1250,10 @@ impl Plan {
     ) -> Result<NodeId, SbroadError> {
         let child_row_len = |child: NodeId, plan: &Plan| -> Result<usize, SbroadError> {
             let child_output = plan.get_relation_node(child)?.output();
-            Ok(plan.get_expression_node(child_output)?.get_row_list().len())
+            Ok(plan
+                .get_expression_node(child_output)?
+                .get_row_list()?
+                .len())
         };
 
         let left_row_len = child_row_len(left, self)?;
@@ -1305,7 +1309,7 @@ impl Plan {
     /// - Row node is not of a row type
     pub fn add_values_row(
         &mut self,
-        expr_row_id: usize,
+        expr_row_id: NodeId,
         col_idx: &mut usize,
     ) -> Result<NodeId, SbroadError> {
         let row = self.get_expression_node(expr_row_id)?;
@@ -1383,7 +1387,7 @@ impl Plan {
 
         // Generate a row of aliases referencing all the children.
         let mut aliases: Vec<NodeId> = Vec::with_capacity(names.len());
-        let columns = last_output.clone_row_list();
+        let columns = last_output.clone_row_list()?;
         for (pos, name) in names.iter().enumerate() {
             let col_id = *columns.get(pos).ok_or_else(|| {
                 SbroadError::UnexpectedNumberOfValues(format_smolstr!(
@@ -1417,7 +1421,7 @@ impl Plan {
     ///
     /// # Errors
     /// - node is not relational
-    pub fn get_relational_output(&self, rel_id: usize) -> Result<usize, SbroadError> {
+    pub fn get_relational_output(&self, rel_id: NodeId) -> Result<NodeId, SbroadError> {
         let rel_node = self.get_relation_node(rel_id)?;
         Ok(rel_node.output())
     }
@@ -1652,7 +1656,9 @@ impl Plan {
 
     /// Sets children for relational node
     pub fn set_relational_children(&mut self, rel_id: NodeId, children: Vec<NodeId>) {
-        if let MutNode::Relational(ref mut rel) = self.get_mut_node(rel_id) {
+        if let MutNode::Relational(ref mut rel) =
+            self.get_mut_node(rel_id).expect("Rel node must be valid.")
+        {
             rel.set_children(children);
         } else {
             panic!("Expected relational node for {rel_id}.");
@@ -1742,12 +1748,11 @@ impl Plan {
     /// # Errors
     /// - Failed to get plan top
     /// - Node returned by the relational iterator is not relational (bug)
-    pub fn is_additional_child(&self, sq_id: usize) -> Result<bool, SbroadError> {
-        for (id, node) in self.nodes.iter().enumerate() {
-            if let Node::Relational(_) = node {
-                if self.is_additional_child_of_rel(id, sq_id)? {
-                    return Ok(true);
-                }
+    pub fn is_additional_child(&self, sq_id: NodeId) -> Result<bool, SbroadError> {
+        let parent_rel_id = self.find_parent_rel(sq_id)?;
+        if let Some(parent_rel_id) = parent_rel_id {
+            if self.is_additional_child_of_rel(parent_rel_id, sq_id)? {
+                return Ok(true);
             }
         }
         Ok(false)
@@ -1794,9 +1799,9 @@ impl Plan {
     pub fn children(&self, rel_id: NodeId) -> Children<'_> {
         let node = self.get_relation_node(rel_id).unwrap();
         match node {
-            Relational::Limit(Limit { child, .. })
-            | Relational::OrderBy(OrderBy { child, .. })
-            | Relational::ScanCte(ScanCte { child, .. }) => Children::Single(child),
+            Relational::Limit(Limit { child, .. }) | Relational::ScanCte(ScanCte { child, .. }) => {
+                Children::Single(child)
+            }
             Relational::Except(Except { left, right, .. })
             | Relational::Intersect(Intersect { left, right, .. })
             | Relational::UnionAll(UnionAll { left, right, .. })
@@ -1805,6 +1810,7 @@ impl Plan {
             | Relational::Update(Update { children, .. })
             | Relational::Join(Join { children, .. })
             | Relational::Having(Having { children, .. })
+            | Relational::OrderBy(OrderBy { children, .. })
             | Relational::Delete(Delete { children, .. })
             | Relational::Insert(Insert { children, .. })
             | Relational::Motion(Motion { children, .. })
diff --git a/sbroad-core/src/ir/operator/tests.rs b/sbroad-core/src/ir/operator/tests.rs
index e1ef355890..48bade8fab 100644
--- a/sbroad-core/src/ir/operator/tests.rs
+++ b/sbroad-core/src/ir/operator/tests.rs
@@ -48,7 +48,7 @@ fn scan_rel() {
     if let Node::Expression(expr) = row {
         let keys: HashSet<_, RepeatableState> = collection! { Key::new(vec![1, 0]) };
         assert_eq!(
-            expr.distribution(),
+            expr.distribution().unwrap(),
             &Distribution::Segment { keys: keys.into() }
         );
     } else {
diff --git a/sbroad-core/src/ir/relation.rs b/sbroad-core/src/ir/relation.rs
index 88573b81c7..cec019bf88 100644
--- a/sbroad-core/src/ir/relation.rs
+++ b/sbroad-core/src/ir/relation.rs
@@ -148,7 +148,7 @@ impl Type {
             "decimal" => Ok(Type::Decimal),
             "double" => Ok(Type::Double),
             "integer" => Ok(Type::Integer),
-            "number" | "numeric" => Ok(Type::Number),
+            "number" => Ok(Type::Number),
             "scalar" => Ok(Type::Scalar),
             "string" | "text" => Ok(Type::String),
             "uuid" => Ok(Type::Uuid),
diff --git a/sbroad-core/src/ir/transformation/bool_in.rs b/sbroad-core/src/ir/transformation/bool_in.rs
index 89548eee8b..9fa2750821 100644
--- a/sbroad-core/src/ir/transformation/bool_in.rs
+++ b/sbroad-core/src/ir/transformation/bool_in.rs
@@ -60,7 +60,7 @@ impl Plan {
             return Ok((top_id, top_id));
         }
 
-        let right_columns = self.get_expression_node(right_id)?.clone_row_list();
+        let right_columns = self.get_expression_node(right_id)?.clone_row_list()?;
         if let Some((first_id, other)) = right_columns.split_first() {
             let new_left_id = left_id;
 
diff --git a/sbroad-core/src/ir/transformation/equality_propagation.rs b/sbroad-core/src/ir/transformation/equality_propagation.rs
index 243d9513e8..68245f5786 100644
--- a/sbroad-core/src/ir/transformation/equality_propagation.rs
+++ b/sbroad-core/src/ir/transformation/equality_propagation.rs
@@ -129,7 +129,7 @@ impl EqClassRef {
                 targets: expr_tgt.clone(),
                 position: *expr_pos,
                 parent: *expr_prt,
-                col_type: expr_type.clone(),
+                col_type: *expr_type,
                 asterisk_source: expr_asterisk_source.clone(),
             });
         }
diff --git a/sbroad-core/src/ir/transformation/redistribution.rs b/sbroad-core/src/ir/transformation/redistribution.rs
index 34aa74247c..fde12b2244 100644
--- a/sbroad-core/src/ir/transformation/redistribution.rs
+++ b/sbroad-core/src/ir/transformation/redistribution.rs
@@ -13,7 +13,7 @@ use crate::ir::distribution::{Distribution, Key, KeySet};
 use crate::ir::expression::ColumnPositionMap;
 use crate::ir::node::expression::Expression;
 use crate::ir::node::relational::{RelOwned, Relational};
-use crate::ir::operator::{Bool, JoinKind, Unary, UpdateStrategy};
+use crate::ir::operator::{Bool, JoinKind, OrderByEntity, Unary, UpdateStrategy};
 
 use crate::ir::node::{
     BoolExpr, Except, GroupBy, Having, Intersect, Join, Limit, NodeId, OrderBy, Projection,
@@ -231,7 +231,7 @@ impl Strategy {
         self.children_policy.insert(child_id, (policy, program));
     }
 
-    fn get_rel_ids(&self) -> AHashSet<usize> {
+    fn get_rel_ids(&self) -> AHashSet<NodeId> {
         let mut vec_ids = Vec::new();
         for id in self.children_policy.keys() {
             vec_ids.push(*id);
@@ -876,7 +876,7 @@ impl Plan {
     ///
     /// # Errors
     /// - If the node is not a row node.
-    fn build_row_map(&self, row_id: NodeId) -> Result<HashMap<usize, usize>, SbroadError> {
+    fn build_row_map(&self, row_id: NodeId) -> Result<HashMap<usize, NodeId>, SbroadError> {
         let columns = self.get_row_list(row_id)?;
         let mut map: HashMap<usize, NodeId> = HashMap::new();
         for (pos, col) in columns.iter().enumerate() {
@@ -1222,7 +1222,7 @@ impl Plan {
                 }
             }
 
-            let Expression::Bool { left, right, .. } = expr else {
+            let Expression::Bool(BoolExpr { left, right, .. }) = expr else {
                 continue;
             };
             let bool_op = BoolOp::from_expr(self, node_id)?;
@@ -1253,7 +1253,7 @@ impl Plan {
             // Lets try to improve the motion policy for the inner join child.
             let left_expr = self.get_expression_node(bool_op.left)?;
             let right_expr = self.get_expression_node(bool_op.right)?;
-            new_inner_policy = match (left_expr, right_expr) {
+            new_inner_policy = match (&left_expr, &right_expr) {
                 (Expression::Arithmetic(_), _) | (_, Expression::Arithmetic(_)) => {
                     MotionPolicy::Full
                 }
@@ -1300,10 +1300,7 @@ impl Plan {
                         }
                     }
                 }
-                (
-                    Expression::Constant(_),
-                    Expression::Bool(_) | Expression::Unary(_),
-                ) => inner_map
+                (Expression::Constant(_), Expression::Bool(_) | Expression::Unary(_)) => inner_map
                     .get(&bool_op.right)
                     .cloned()
                     .unwrap_or(MotionPolicy::Full),
@@ -1555,8 +1552,6 @@ impl Plan {
             strategy.add_child(*sq, MotionPolicy::Full, Program::default());
         }
 
-        // TODO: this code won't be executed because of (Single, Single) check above.
-        //
         // If one child has Distribution::Global and the other child
         // Distribution::Single, then motion is not needed.
         // The fastest way is to execute the subtree on single node,
@@ -1803,8 +1798,6 @@ impl Plan {
         &mut self,
         rel_id: NodeId,
     ) -> Result<Strategy, SbroadError> {
-        // TODO: This logic seems strange to me as soon as we add Motion::Full over child
-        //       that is already a Motion.
         let mut map = Strategy::new(rel_id);
         let child_id = self.dml_child_id(rel_id)?;
         let child_node = self.get_relation_node(child_id)?;
@@ -1889,7 +1882,11 @@ impl Plan {
     /// select `bucket_id` as a from t1
     /// except
     /// select `bucket_id` as b from t1
-    fn is_except_on_bucket_id(&self, left_id: NodeId, right_id: NodeId) -> Result<bool, SbroadError> {
+    fn is_except_on_bucket_id(
+        &self,
+        left_id: NodeId,
+        right_id: NodeId,
+    ) -> Result<bool, SbroadError> {
         let mut context = self.context_mut();
         let Some(left_shard_positions) =
             context.get_shard_columns_positions(left_id, self)?.copied()
@@ -2155,7 +2152,7 @@ impl Plan {
     }
 
     /// Set dist from subqueries or clone it from output.
-    fn try_dist_from_subqueries(&mut self, id: usize, output: usize) -> Result<(), SbroadError> {
+    fn try_dist_from_subqueries(&mut self, id: NodeId, output: NodeId) -> Result<(), SbroadError> {
         if let Some(dist) = self.dist_from_subqueries(id)? {
             self.set_dist(output, dist)?;
         } else {
@@ -2173,8 +2170,8 @@ impl Plan {
     /// the `already_fixed`, but we identify them checking whether the node is covered with Motion.
     fn fix_additional_subqueries(
         &mut self,
-        rel_id: usize,
-        already_fixed: &AHashSet<usize>,
+        rel_id: NodeId,
+        already_fixed: &AHashSet<NodeId>,
     ) -> Result<(), SbroadError> {
         let mut strategy = Strategy::new(rel_id);
         let rel_required_children_len = self
diff --git a/sbroad-core/src/ir/transformation/redistribution/dml.rs b/sbroad-core/src/ir/transformation/redistribution/dml.rs
index 0388af48a4..2b1c83bda6 100644
--- a/sbroad-core/src/ir/transformation/redistribution/dml.rs
+++ b/sbroad-core/src/ir/transformation/redistribution/dml.rs
@@ -12,7 +12,7 @@ use super::{MotionKey, Target};
 
 impl Plan {
     /// Return first child of `Insert` node
-    pub fn dml_child_id(&self, dml_node_id: usize) -> Result<usize, SbroadError> {
+    pub fn dml_child_id(&self, dml_node_id: NodeId) -> Result<NodeId, SbroadError> {
         let dml_node = self.get_relation_node(dml_node_id)?;
         if let Relational::Insert(Insert { children, .. })
         | Relational::Update(Update { children, .. })
@@ -63,7 +63,7 @@ impl Plan {
         // output columns.
         let child_id = self.dml_child_id(insert_id)?;
         let child_output_id = self.get_relation_node(child_id)?.output();
-        let child_row = self.get_expression_node(child_output_id)?.get_row_list();
+        let child_row = self.get_row_list(child_output_id)?;
         if columns.len() != child_row.len() {
             return Err(SbroadError::Invalid(
                 Entity::Node,
@@ -118,7 +118,7 @@ impl Plan {
     }
 
     /// Return the table for given `Insert` node
-    pub fn dml_node_table(&self, node_id: usize) -> Result<&Table, SbroadError> {
+    pub fn dml_node_table(&self, node_id: NodeId) -> Result<&Table, SbroadError> {
         let node = self.get_relation_node(node_id)?;
         if let Relational::Insert(Insert { relation, .. })
         | Relational::Update(Update { relation, .. })
diff --git a/sbroad-core/src/ir/transformation/redistribution/groupby.rs b/sbroad-core/src/ir/transformation/redistribution/groupby.rs
index be6822a56c..5c713c747b 100644
--- a/sbroad-core/src/ir/transformation/redistribution/groupby.rs
+++ b/sbroad-core/src/ir/transformation/redistribution/groupby.rs
@@ -1830,7 +1830,9 @@ impl Plan {
         }
 
         if let Some(having_id) = having_id {
-            if let Relational::Having(Having { filter, output, .. }) = self.get_relation_node(having_id)? {
+            if let Relational::Having(Having { filter, output, .. }) =
+                self.get_relation_node(having_id)?
+            {
                 let (filter, output) = (*filter, *output);
                 let strategy = self.resolve_sub_query_conflicts(having_id, filter)?;
                 let fixed_subquery_ids = strategy.get_rel_ids();
diff --git a/sbroad-core/src/ir/transformation/redistribution/tests/segment.rs b/sbroad-core/src/ir/transformation/redistribution/tests/segment.rs
index 2064042114..a1819b2342 100644
--- a/sbroad-core/src/ir/transformation/redistribution/tests/segment.rs
+++ b/sbroad-core/src/ir/transformation/redistribution/tests/segment.rs
@@ -1,6 +1,5 @@
 use crate::collection;
 use crate::ir::distribution::{Distribution, Key};
-use crate::ir::expression::Expression;
 use crate::ir::helpers::RepeatableState;
 use crate::ir::node::{Node64, NodeId};
 use crate::ir::relation::Column;
diff --git a/sbroad-core/src/ir/tree/relation.rs b/sbroad-core/src/ir/tree/relation.rs
index f6bf0510e5..ebe618031e 100644
--- a/sbroad-core/src/ir/tree/relation.rs
+++ b/sbroad-core/src/ir/tree/relation.rs
@@ -2,7 +2,7 @@ use std::cell::RefCell;
 
 use super::TreeIterator;
 use crate::ir::node::relational::Relational;
-use crate::ir::node::{ArenaType, GroupBy, Limit, NodeId, OrderBy, ScanCte};
+use crate::ir::node::{ArenaType, Limit, NodeId, ScanCte};
 use crate::ir::{Node, Nodes};
 
 trait RelationalTreeIterator<'nodes>: TreeIterator<'nodes> {}
@@ -61,9 +61,7 @@ impl<'n> Iterator for RelationalIterator<'n> {
     }
 }
 
-fn relational_next<'nodes>(
-    iter: &mut impl RelationalTreeIterator<'nodes>,
-) -> Option<&'nodes usize> {
+fn relational_next<'nodes>(iter: &mut impl RelationalTreeIterator<'nodes>) -> Option<NodeId> {
     let next = iter.get_nodes().get(iter.get_current());
     match next {
         Some(node) => match node {
@@ -89,15 +87,16 @@ fn relational_next<'nodes>(
                     let children = node.children();
                     if step < children.len() {
                         *iter.get_child().borrow_mut() += 1;
-                        return children.get(step);
+                        return children.get(step).copied();
                     }
                     None
                 }
-                Relational::ScanCte { child, .. } | Relational::Limit { child, .. } => {
+                Relational::ScanCte(ScanCte { child, .. })
+                | Relational::Limit(Limit { child, .. }) => {
                     let step = *iter.get_child().borrow();
                     if step == 0 {
                         *iter.get_child().borrow_mut() += 1;
-                        return Some(child);
+                        return Some(child).copied();
                     }
                     None
                 }
@@ -109,8 +108,8 @@ fn relational_next<'nodes>(
             | Node::Ddl(_)
             | Node::Acl(_)
             | Node::Block(_)
-            | Node::Plugin(_),
-        )
-        | None => None,
+            | Node::Plugin(_) => None,
+        },
+        None => None,
     }
 }
diff --git a/sbroad-core/src/ir/tree/subtree.rs b/sbroad-core/src/ir/tree/subtree.rs
index 2a7a8cdcf0..4cc268f409 100644
--- a/sbroad-core/src/ir/tree/subtree.rs
+++ b/sbroad-core/src/ir/tree/subtree.rs
@@ -251,7 +251,7 @@ fn subtree_next<'plan>(
                                 {
                                     let is_additional_child = iter
                                         .get_plan()
-                                        .is_additional_child_of_rel(parent_id, *rel_id)
+                                        .is_additional_child_of_rel(parent_id, rel_id)
                                         .expect(
                                             "Relational node failed to check additional child.",
                                         );
@@ -364,7 +364,7 @@ fn subtree_next<'plan>(
                     let step = *iter.get_child().borrow();
                     if step == 0 {
                         *iter.get_child().borrow_mut() += 1;
-                        return children.get(step);
+                        return children.get(step).copied();
                     }
                     let mut col_idx = step - 1;
                     while col_idx < order_by_elements.len() {
diff --git a/sbroad-core/src/ir/tree/tests.rs b/sbroad-core/src/ir/tree/tests.rs
index cccc7ac787..2a36ff61a7 100644
--- a/sbroad-core/src/ir/tree/tests.rs
+++ b/sbroad-core/src/ir/tree/tests.rs
@@ -239,7 +239,8 @@ fn subtree_dfs_post() {
     let row_children = plan
         .get_expression_node(proj_row_id)
         .unwrap()
-        .clone_row_list();
+        .clone_row_list()
+        .unwrap();
     let alias_id = row_children.first().unwrap();
     let Expression::Alias(Alias {
         child: c_ref_id, ..
-- 
GitLab