From e01bcb95f40eab7d9250b0163928ff74e57b948a Mon Sep 17 00:00:00 2001
From: Denis Smirnov <sd@picodata.io>
Date: Wed, 24 Apr 2024 14:15:09 +0700
Subject: [PATCH] feat: build syntax tree with stack rather then with map

The map requires plan is uniqueness among the syntax nodes, but
CTE violates this restrictions. So, migrate to the stack traversal.
---
 .../test_app/test/integration/insert_test.lua |   65 +-
 sbroad-core/src/backend/sql/ir.rs             |    2 -
 sbroad-core/src/backend/sql/tree.rs           | 1581 ++++++++++-------
 sbroad-core/src/backend/sql/tree/tests.rs     |    2 +-
 sbroad-core/src/executor/ir.rs                |   31 +-
 sbroad-core/src/executor/tests/exec_plan.rs   |    7 +-
 sbroad-core/src/frontend/sql/ir/tests/cte.rs  |    1 -
 sbroad-core/src/ir/operator.rs                |    8 +
 .../sql_order_selection_syntax_nodes.yaml     |   38 +-
 9 files changed, 973 insertions(+), 762 deletions(-)

diff --git a/sbroad-cartridge/test_app/test/integration/insert_test.lua b/sbroad-cartridge/test_app/test/integration/insert_test.lua
index b7370d3d1..7cf41e70c 100644
--- a/sbroad-cartridge/test_app/test/integration/insert_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/insert_test.lua
@@ -281,59 +281,42 @@ g.test_insert_8 = function()
 
     local r, err = api:call("sbroad.execute", { [[VALUES (?, ?, ?), (?, ?, ?)]], { 8, 8, box.NULL, 9, 9, 'hello' } })
     t.assert_equals(err, nil)
-    t.assert_equals(r, {
-        metadata = {
-            {name = "COLUMN_4", type = "integer"},
-            {name = "COLUMN_5", type = "integer"},
-            {name = "COLUMN_6", type = "boolean"},
-        },
-        rows = {
-            { 8, 8, box.NULL },
-            { 9, 9, 'hello' }
-        },
+    t.assert_items_equals(r["metadata"], {
+        {name = "COLUMN_4", type = "integer"},
+        {name = "COLUMN_5", type = "integer"},
+        {name = "COLUMN_6", type = "text"},
     })
+    t.assert_items_equals(r["rows"], { { 8, 8, box.NULL }, { 9, 9, 'hello' } })
 
-    r, err = api:call("sbroad.execute", { [[VALUES (?, ?, ?), (?, ?, ?)]], { 9, 9, 'hello', 8, 8, box.NULL } })
+    r, err = api:call(
+        "sbroad.execute",
+        { [[VALUES (?, ?, ?), (?, ?, ?)]], { 9, 9, 'hello', 8, 8, box.NULL } }
+    )
     t.assert_equals(err, nil)
-    t.assert_equals(r, {
-        metadata = {
-            {name = "COLUMN_4", type = "integer"},
-            {name = "COLUMN_5", type = "integer"},
-            {name = "COLUMN_6", type = "text"},
-        },
-        rows = {
-            { 9, 9, 'hello' },
-            { 8, 8, box.NULL }
-        },
+    t.assert_items_equals(r["metadata"], {
+        {name = "COLUMN_4", type = "integer"},
+        {name = "COLUMN_5", type = "integer"},
+        {name = "COLUMN_6", type = "boolean"},
     })
+    t.assert_items_equals(r["rows"], { { 9, 9, 'hello' }, { 8, 8, box.NULL } })
 
     r, err = api:call("sbroad.execute", { [[VALUES (8, 8, null), (9, 9, 'hello')]], {} })
     t.assert_equals(err, nil)
-    t.assert_equals(r, {
-        metadata = {
-            {name = "COLUMN_4", type = "integer"},
-            {name = "COLUMN_5", type = "integer"},
-            {name = "COLUMN_6", type = "boolean"},
-        },
-        rows = {
-            { 8, 8, box.NULL },
-            { 9, 9, 'hello' }
-        },
+    t.assert_items_equals(r["metadata"], {
+        {name = "COLUMN_4", type = "integer"},
+        {name = "COLUMN_5", type = "integer"},
+        {name = "COLUMN_6", type = "text"},
     })
+    t.assert_items_equals(r["rows"], { { 8, 8, box.NULL }, { 9, 9, 'hello' } })
 
     r, err = api:call("sbroad.execute", { [[VALUES (9, 9, 'hello'), (8, 8, null)]], {} })
     t.assert_equals(err, nil)
-    t.assert_equals(r, {
-        metadata = {
-            {name = "COLUMN_4", type = "integer"},
-            {name = "COLUMN_5", type = "integer"},
-            {name = "COLUMN_6", type = "text"},
-        },
-        rows = {
-            { 9, 9, 'hello' },
-            { 8, 8, box.NULL }
-        },
+    t.assert_items_equals(r["metadata"], {
+        {name = "COLUMN_4", type = "integer"},
+        {name = "COLUMN_5", type = "integer"},
+        {name = "COLUMN_6", type = "boolean"},
     })
+    t.assert_items_equals(r["rows"], { { 9, 9, 'hello' }, { 8, 8, box.NULL } })
 
     r, err = api:call("sbroad.execute", { [[INSERT INTO "space_simple_shard_key"
     ("sysOp", "id", "name") VALUES (?, ?, ?), (?, ?, ?)]], { 8, 8, box.NULL, 9, 9, 'hello' } })
diff --git a/sbroad-core/src/backend/sql/ir.rs b/sbroad-core/src/backend/sql/ir.rs
index 3b3837e6f..629db2efa 100644
--- a/sbroad-core/src/backend/sql/ir.rs
+++ b/sbroad-core/src/backend/sql/ir.rs
@@ -30,13 +30,11 @@ pub struct PatternWithParams {
     // Name of the tracer to use
     pub tracer: Option<String>,
 }
-
 impl PartialEq for PatternWithParams {
     fn eq(&self, other: &Self) -> bool {
         self.pattern == other.pattern && self.params == other.params
     }
 }
-
 impl TryFrom<FunctionArgs> for PatternWithParams {
     type Error = SbroadError;
 
diff --git a/sbroad-core/src/backend/sql/tree.rs b/sbroad-core/src/backend/sql/tree.rs
index c9e5a0c93..22f56026b 100644
--- a/sbroad-core/src/backend/sql/tree.rs
+++ b/sbroad-core/src/backend/sql/tree.rs
@@ -1,10 +1,8 @@
-use ahash::RandomState;
 use serde::{Deserialize, Serialize};
 use smol_str::{format_smolstr, SmolStr};
-use std::collections::HashMap;
 use std::mem::take;
 
-use crate::errors::{Action, Entity, SbroadError};
+use crate::errors::{Entity, SbroadError};
 use crate::executor::ir::ExecutionPlan;
 use crate::ir::expression::{Expression, FunctionFeature, TrimKind};
 use crate::ir::operator::{Bool, OrderByElement, OrderByEntity, OrderByType, Relational, Unary};
@@ -270,9 +268,10 @@ impl SyntaxNode {
 /// Storage for the syntax nodes.
 #[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct SyntaxNodes {
+    /// Syntax node tree (positions in the vector act like identifiers).
     pub(crate) arena: Vec<SyntaxNode>,
-    /// Map of { node_id from `Plan` arena -> node_id from `SyntaxNodes`(Self) arena }.
-    map: HashMap<usize, usize, RandomState>,
+    /// A stack with syntax node identifiers (required on the tree building step).
+    stack: Vec<usize>,
 }
 
 #[derive(Debug)]
@@ -322,160 +321,36 @@ fn syntax_next<'nodes>(iter: &mut SyntaxIterator<'nodes>) -> Option<&'nodes usiz
 }
 
 impl SyntaxNodes {
-    /// Add sub-query syntax node
-    ///
-    /// # Errors
-    /// - sub-query in plan tree is invalid
-    fn add_sq(&mut self, rel: &Relational, id: usize) -> Result<usize, SbroadError> {
-        if let Relational::ScanSubQuery {
-            children, alias, ..
-        } = rel
-        {
-            let right_id = *children.first().ok_or_else(|| {
-                SbroadError::UnexpectedNumberOfValues("Sub-query has no children.".into())
-            })?;
-            let mut children: Vec<usize> = vec![
-                self.push_syntax_node(SyntaxNode::new_open()),
-                self.get_syntax_node_id(right_id)?,
-                self.push_syntax_node(SyntaxNode::new_close()),
-            ];
-            if let Some(name) = alias {
-                children.push(self.push_syntax_node(SyntaxNode::new_alias(name.clone())));
-            }
-            let sn = SyntaxNode::new_pointer(id, None, children);
-            Ok(self.push_syntax_node(sn))
-        } else {
-            Err(SbroadError::Invalid(
-                Entity::SyntaxNode,
-                Some("current node is not a sub-query".into()),
-            ))
-        }
+    fn get_sn(&self, id: usize) -> &SyntaxNode {
+        self.arena
+            .get(id)
+            .unwrap_or_else(|| panic!("syntax node with id {id} must exist"))
     }
 
-    fn add_cte(&mut self, plan: &Plan, id: usize) -> Result<usize, SbroadError> {
-        let cte = plan.get_relation_node(id)?;
-        let Relational::ScanCte { alias, child, .. } = cte else {
-            panic!("expected CTE node");
-        };
-        let child_sp_id = self.get_syntax_node_id(*child)?;
-        let children: Vec<usize> = vec![
-            self.push_syntax_node(SyntaxNode::new_open()),
-            child_sp_id,
-            self.push_syntax_node(SyntaxNode::new_close()),
-            self.push_syntax_node(SyntaxNode::new_alias(alias.clone())),
-        ];
-        let sn = SyntaxNode::new_pointer(id, None, children);
-        Ok(self.push_syntax_node(sn))
+    fn get_mut_sn(&mut self, id: usize) -> &mut SyntaxNode {
+        self.arena
+            .get_mut(id)
+            .unwrap_or_else(|| panic!("syntax node with id {id} must exist"))
     }
 
-    fn add_order_by(&mut self, plan: &Plan, id: usize) -> Result<usize, SbroadError> {
-        let order_by = plan.get_relation_node(id)?;
-        let Relational::OrderBy {
-            order_by_elements,
-            child,
-            ..
-        } = order_by
-        else {
-            panic!("expect ORDER BY node");
-        };
-        let mut children: Vec<usize> = Vec::with_capacity(order_by_elements.len() * 3 - 1);
-        let mut wrapped_syntax_nodes =
-            |elem: &OrderByElement, need_comma: bool| -> Result<[Option<usize>; 3], SbroadError> {
-                let mut nodes = [None, None, None];
-                match elem.entity {
-                    OrderByEntity::Expression { expr_id } => {
-                        nodes[0] = Some(self.get_syntax_node_id(expr_id)?);
-                    }
-                    OrderByEntity::Index { value } => {
-                        let sn = SyntaxNode::new_order_index(value);
-                        nodes[0] = Some(self.push_syntax_node(sn));
-                    }
-                }
-                if let Some(order_type) = &elem.order_type {
-                    let sn = SyntaxNode::new_order_type(order_type);
-                    nodes[1] = Some(self.push_syntax_node(sn));
-                }
-                if need_comma {
-                    nodes[2] = Some(self.push_syntax_node(SyntaxNode::new_comma()));
-                }
-                Ok(nodes)
-            };
-        if let Some((last, other)) = order_by_elements.split_last() {
-            for elem in other {
-                for id in wrapped_syntax_nodes(elem, true)?.into_iter().flatten() {
-                    children.push(id);
-                }
-            }
-            for id in wrapped_syntax_nodes(last, false)?.into_iter().flatten() {
-                children.push(id);
+    fn push_sn_plan(&mut self, node: SyntaxNode) -> usize {
+        let id = self.next_id();
+        match node.data {
+            SyntaxData::PlanId(_) | SyntaxData::Parameter(_) => self.stack.push(id),
+            _ => {
+                unreachable!("Expected a plan node wrapper.");
             }
         }
-
-        let sn = SyntaxNode::new_pointer(id, Some(self.get_syntax_node_id(*child)?), children);
-        Ok(self.push_syntax_node(sn))
-    }
-
-    /// Construct syntax nodes from the YAML file.
-    ///
-    /// # Errors
-    /// Returns `SbroadError` when the YAML nodes arena is invalid.
-    #[allow(dead_code)]
-    pub fn from_yaml(s: &str) -> Result<Self, SbroadError> {
-        let nodes: SyntaxNodes = match serde_yaml::from_str(s) {
-            Ok(p) => p,
-            Err(e) => {
-                return Err(SbroadError::FailedTo(
-                    Action::Serialize,
-                    Some(Entity::SyntaxNodes),
-                    format_smolstr!("{e:?}"),
-                ))
-            }
-        };
-        Ok(nodes)
-    }
-
-    /// Get a syntax node from arena
-    ///
-    /// # Errors
-    /// - current node is invalid (doesn't exist in arena)
-    pub fn get_syntax_node(&self, id: usize) -> Result<&SyntaxNode, SbroadError> {
-        self.arena.get(id).ok_or_else(|| {
-            SbroadError::NotFound(Entity::Node, format_smolstr!("from arena with index {id}"))
-        })
-    }
-
-    /// Get a mutable syntax node from arena
-    ///
-    /// # Errors
-    /// - current node is invalid (doesn't exist in arena)
-    pub fn get_mut_syntax_node(&mut self, id: usize) -> Result<&mut SyntaxNode, SbroadError> {
-        self.arena.get_mut(id).ok_or_else(|| {
-            SbroadError::NotFound(
-                Entity::Node,
-                format_smolstr!("(mutable) from arena with index {id}"),
-            )
-        })
-    }
-
-    /// Get syntax node id by the plan node's one
-    ///
-    /// # Errors
-    /// - nothing was found
-    fn get_syntax_node_id(&self, plan_id: usize) -> Result<usize, SbroadError> {
-        self.map.get(&plan_id).copied().ok_or_else(|| {
-            SbroadError::NotFound(Entity::Node, format_smolstr!("({plan_id}) in the map"))
-        })
+        self.arena.push(node);
+        id
     }
 
-    /// Push a new syntax node to arena
-    pub fn push_syntax_node(&mut self, node: SyntaxNode) -> usize {
+    fn push_sn_non_plan(&mut self, node: SyntaxNode) -> usize {
         let id = self.next_id();
-        match node.data {
-            SyntaxData::PlanId(plan_id) | SyntaxData::Parameter(plan_id) => {
-                self.map.insert(plan_id, id);
-            }
-            _ => {}
-        }
+        assert!(!matches!(
+            node.data,
+            SyntaxData::PlanId(_) | SyntaxData::Parameter(_)
+        ));
         self.arena.push(node);
         id
     }
@@ -489,9 +364,10 @@ impl SyntaxNodes {
     /// Constructor with pre-allocated memory
     #[must_use]
     pub fn with_capacity(capacity: usize) -> Self {
+        let depth = capacity.ilog2() as usize;
         SyntaxNodes {
             arena: Vec::with_capacity(capacity),
-            map: HashMap::with_capacity_and_hasher(capacity, RandomState::new()),
+            stack: Vec::with_capacity(depth),
         }
     }
 }
@@ -532,7 +408,7 @@ impl Select {
         branch: Option<Branch>,
         id: usize,
     ) -> Result<Option<Select>, SbroadError> {
-        let sn = sp.nodes.get_syntax_node(id)?;
+        let sn = sp.nodes.get_sn(id);
         if let Some(Node::Relational(Relational::Projection { .. })) = sp.get_plan_node(&sn.data)? {
             let mut select = Select {
                 parent,
@@ -543,10 +419,10 @@ impl Select {
 
             // Iterate over the left branch subtree of the projection node to find
             // the scan node (leaf node without children).
-            let mut node = sp.nodes.get_syntax_node(id)?;
+            let mut node = sp.nodes.get_sn(id);
             loop {
                 let left_id = node.left_id_or_err()?;
-                let sn_left = sp.nodes.get_syntax_node(left_id)?;
+                let sn_left = sp.nodes.get_sn(left_id);
                 let plan_node_left = sp.plan_node_or_err(&sn_left.data)?;
                 if let Node::Relational(
                     Relational::ScanRelation { .. }
@@ -599,7 +475,62 @@ pub struct SyntaxPlan<'p> {
 
 #[allow(dead_code)]
 impl<'p> SyntaxPlan<'p> {
-    /// Add an IR plan node to the syntax tree.
+    /// Checks that the syntax node wraps an expected plan node identifier.
+    ///
+    /// # Panics
+    /// - syntax node wraps non-plan node;
+    /// - plan node is not the one we expect;
+    fn check_plan_node(&self, sn_id: usize, plan_id: usize) {
+        let sn = self.nodes.get_sn(sn_id);
+        let SyntaxNode {
+            data: SyntaxData::PlanId(id) | SyntaxData::Parameter(id),
+            ..
+        } = sn
+        else {
+            panic!("Expected plan syntax node");
+        };
+        if *id != plan_id {
+            // If it is a motion and we need its child instead.
+            let plan = self.plan.get_ir_plan();
+            let node = plan.get_node(plan_id).expect("node in the plan must exist");
+            match node {
+                Node::Relational(Relational::Motion { children, .. }) => {
+                    let child_id = *children.first().expect("MOTION child must exist");
+                    if *id == child_id {
+                        return;
+                    }
+                }
+                Node::Expression(Expression::Row { .. }) => {
+                    let rel_ids = plan
+                        .get_relational_nodes_from_row(plan_id)
+                        .expect("row relational nodes");
+                    if rel_ids.contains(id) {
+                        return;
+                    }
+                }
+                _ => {}
+            }
+            panic!("Expected plan node {plan_id} but got {id}");
+        }
+    }
+
+    /// Push a syntax node identifier on the top of the stack.
+    fn push_on_stack(&mut self, sn_id: usize) {
+        self.nodes.stack.push(sn_id);
+    }
+
+    /// Pop syntax node identifier from the stack with a check, that the popped syntax
+    /// node wraps an expected plan node.
+    fn pop_from_stack(&mut self, plan_id: usize) -> usize {
+        let sn_id = self.nodes.stack.pop().expect("stack must be non-empty");
+        self.check_plan_node(sn_id, plan_id);
+        sn_id
+    }
+
+    /// Add an IR plan node to the syntax tree. Keep in mind, that this function expects
+    /// that the plan node's children are iterated with `subtree_iter()` on traversal.
+    /// As a result, the syntax node children on the stack should be popped in the reverse
+    /// order.
     ///
     /// # Errors
     /// - Failed to translate an IR plan node to a syntax node.
@@ -608,563 +539,833 @@ impl<'p> SyntaxPlan<'p> {
     /// - Failed to find a node in the plan.
     #[allow(clippy::too_many_lines)]
     #[allow(unused_variables)]
-    pub fn add_plan_node(&mut self, id: usize) -> Result<usize, SbroadError> {
+    pub fn add_plan_node(&mut self, id: usize) {
         let ir_plan = self.plan.get_ir_plan();
-        let node = ir_plan.get_node(id)?;
+        let node = ir_plan
+            .get_node(id)
+            .expect("node {id} must exist in the plan");
         match node {
-            Node::Ddl(..) => Err(SbroadError::Invalid(
-                Entity::SyntaxPlan,
-                Some(format_smolstr!(
-                    "DDL node {node:?} is not supported in the syntax plan"
-                )),
-            )),
-            Node::Acl(..) => Err(SbroadError::Invalid(
-                Entity::SyntaxPlan,
-                Some(format_smolstr!(
-                    "ACL node {node:?} is not supported in the syntax plan"
-                )),
-            )),
-            Node::Block(..) => Err(SbroadError::Invalid(
-                Entity::SyntaxPlan,
-                Some(format_smolstr!(
-                    "Block node {node:?} is not supported in the syntax plan"
-                )),
-            )),
+            Node::Ddl(..) => panic!("DDL node {node:?} is not supported in the syntax plan"),
+            Node::Acl(..) => panic!("ACL node {node:?} is not supported in the syntax plan"),
+            Node::Block(..) => panic!("Block node {node:?} is not supported in the syntax plan"),
             Node::Parameter => {
                 let sn = SyntaxNode::new_parameter(id);
-                Ok(self.nodes.push_syntax_node(sn))
+                self.nodes.push_sn_plan(sn);
             }
             Node::Relational(rel) => match rel {
                 Relational::Insert { .. }
                 | Relational::Delete { .. }
-                | Relational::Update { .. } => Err(SbroadError::Invalid(
-                    Entity::SyntaxPlan,
-                    Some(format_smolstr!(
-                        "DML node {node:?} is not supported in the syntax plan"
-                    )),
-                )),
-                Relational::Join {
-                    children,
-                    condition,
-                    ..
-                } => {
-                    let left_id = *children.first().ok_or_else(|| {
-                        SbroadError::UnexpectedNumberOfValues("Inner Join has no children.".into())
-                    })?;
-                    let right_id = *children.get(1).ok_or_else(|| {
-                        SbroadError::NotFound(
-                            Entity::Node,
-                            "that is Inner Join right child.".into(),
-                        )
-                    })?;
-                    let condition_id = match self.snapshot {
-                        Snapshot::Latest => *condition,
-                        Snapshot::Oldest => *ir_plan
-                            .undo
-                            .get_oldest(condition)
-                            .map_or_else(|| condition, |id| id),
-                    };
-
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(left_id)?),
-                        vec![
-                            self.nodes.get_syntax_node_id(right_id)?,
-                            self.nodes.push_syntax_node(SyntaxNode::new_condition()),
-                            self.nodes.get_syntax_node_id(condition_id)?,
-                        ],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::Projection {
-                    children, output, ..
-                } => {
-                    let left_id = *children.first().ok_or_else(|| {
-                        SbroadError::UnexpectedNumberOfValues("Projection has no children.".into())
-                    })?;
-                    // We don't need the row node itself, only its children.
-                    // Otherwise we'll produce redundant parentheses between
-                    // `SELECT` and `FROM`.
-                    let expr = ir_plan.get_expression_node(*output)?;
-                    if let Expression::Row { list, .. } = expr {
-                        let mut nodes: Vec<usize> = Vec::with_capacity(list.len() * 2);
-                        if let Some((last, elements)) = list.split_last() {
-                            for elem in elements {
-                                nodes.push(self.nodes.get_syntax_node_id(*elem)?);
-                                nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_comma()));
-                            }
-                            nodes.push(self.nodes.get_syntax_node_id(*last)?);
-                            nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_from()));
-                            let sn = SyntaxNode::new_pointer(
-                                id,
-                                Some(self.nodes.get_syntax_node_id(left_id)?),
-                                nodes,
-                            );
-                            return Ok(self.nodes.push_syntax_node(sn));
-                        }
-                    }
-                    Err(SbroadError::Invalid(Entity::Node, None))
-                }
-                Relational::OrderBy { .. } => self.nodes.add_order_by(ir_plan, id),
-                Relational::ScanCte { .. } => self.nodes.add_cte(ir_plan, id),
-                Relational::ScanSubQuery { .. } => self.nodes.add_sq(rel, id),
-                Relational::GroupBy {
-                    children, gr_cols, ..
-                } => {
-                    let left_id = *children.first().ok_or_else(|| {
-                        SbroadError::UnexpectedNumberOfValues("GroupBy has no children.".into())
-                    })?;
-                    let mut right: Vec<usize> = Vec::with_capacity(gr_cols.len() * 2);
-                    if let Some((last, other)) = gr_cols.split_last() {
-                        for col_id in other {
-                            right.push(self.nodes.get_syntax_node_id(*col_id)?);
-                            right.push(self.nodes.push_syntax_node(SyntaxNode::new_comma()));
-                        }
-                        right.push(self.nodes.get_syntax_node_id(*last)?);
-                    }
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(left_id)?),
-                        right,
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::Selection {
-                    children, filter, ..
-                }
-                | Relational::Having {
-                    children, filter, ..
-                } => {
-                    let left_id = *children.first().ok_or_else(|| {
-                        SbroadError::UnexpectedNumberOfValues(format_smolstr!(
-                            "{node:?} has no children."
-                        ))
-                    })?;
-                    let filter_id = match self.snapshot {
-                        Snapshot::Latest => *filter,
-                        Snapshot::Oldest => *ir_plan
-                            .undo
-                            .get_oldest(filter)
-                            .map_or_else(|| filter, |id| id),
-                    };
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(left_id)?),
-                        vec![self.nodes.get_syntax_node_id(filter_id)?],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::Except { left, right, .. }
-                | Relational::Intersect { left, right, .. }
-                | Relational::Union { left, right, .. }
-                | Relational::UnionAll { left, right, .. } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(*left)?),
-                        vec![self.nodes.get_syntax_node_id(*right)?],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::ScanRelation { alias, .. } => {
-                    let children: Vec<usize> = if let Some(name) = alias {
-                        vec![self
-                            .nodes
-                            .push_syntax_node(SyntaxNode::new_alias(name.clone()))]
-                    } else {
-                        Vec::new()
-                    };
-                    let sn = SyntaxNode::new_pointer(id, None, children);
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::Motion {
-                    policy,
-                    children,
-                    is_child_subquery,
-                    program,
-                    output,
-                    ..
-                } => {
-                    if let MotionPolicy::LocalSegment { .. } = policy {
-                        #[cfg(feature = "mock")]
-                        {
-                            // We should materialize the subquery on the storage.
-                            // Honestly, this SQL is not valid and should never be
-                            // generated in runtime, but let's leave it for testing.
-                            if let Some(child_id) = children.first() {
-                                let sn = SyntaxNode::new_pointer(
-                                    id,
-                                    Some(self.nodes.get_syntax_node_id(*child_id)?),
-                                    vec![],
-                                );
-                                return Ok(self.nodes.push_syntax_node(sn));
-                            }
-                        }
-                        #[cfg(not(feature = "mock"))]
-                        {
-                            return Err(SbroadError::Invalid(
-                                Entity::Node,
-                                Some(
-                                    "LocalSegment motion policy is not supported in the syntax plan."
-                                        .into(),
-                                ),
-                            ));
-                        }
-                    }
-                    if let Some(op) = program
-                        .0
-                        .iter()
-                        .find(|op| matches!(op, MotionOpcode::SerializeAsEmptyTable(_)))
-                    {
-                        let is_enabled = matches!(op, MotionOpcode::SerializeAsEmptyTable(true));
-                        if is_enabled {
-                            let ir = self.plan.get_ir_plan();
-                            let output_cols = ir.get_row_list(*output)?;
-                            // We need to preserve types when doing `select null`,
-                            // otherwise tarantool will cast it to `scalar`.
-                            let mut select_columns = Vec::with_capacity(output_cols.len());
-                            for col in output_cols {
-                                let ref_id = ir
-                                    .get_child_under_alias(*col)
-                                    .expect("expected motion output to be a row of aliases!");
-                                let Expression::Reference { col_type, .. } =
-                                    ir.get_expression_node(ref_id)?
-                                else {
-                                    panic!("expected Reference under Alias in Motion output");
-                                };
-                                select_columns.push(format_smolstr!("cast(null as {col_type})"));
-                            }
-                            let empty_select =
-                                format_smolstr!("select {} where false", select_columns.join(","));
-                            let inline_id = self
-                                .nodes
-                                .push_syntax_node(SyntaxNode::new_inline(&empty_select));
-                            let pointer_id = self.nodes.push_syntax_node(SyntaxNode::new_pointer(
-                                id,
-                                None,
-                                vec![inline_id],
-                            ));
-                            return Ok(pointer_id);
-                        }
-                        let child_plan_id = self.plan.get_ir_plan().get_relational_child(id, 0)?;
-                        let child_sp_id = *self.nodes.map.get(&child_plan_id).ok_or_else(|| {
-                            SbroadError::Invalid(
-                                Entity::SyntaxPlan,
-                                Some(format_smolstr!(
-                                    "motion child {child_plan_id} is not found in map"
-                                )),
-                            )
-                        })?;
-                        self.nodes.map.insert(id, child_sp_id);
-                        return Ok(child_sp_id);
-                    }
-                    let vtable = self.plan.get_motion_vtable(id)?;
-                    let vtable_alias = vtable.get_alias();
-
-                    // There are some cases when motion child is not a `SubQuery` and when
-                    // it has an alias. E.g. in case of a `INSERT ... SELECT ...` its child
-                    // may be a `Projection.
-                    let children = if *is_child_subquery || vtable_alias.is_some() {
-                        let mut children: Vec<usize> = vec![
-                            self.nodes.push_syntax_node(SyntaxNode::new_open()),
-                            self.nodes.push_syntax_node(SyntaxNode::new_vtable(id)),
-                            self.nodes.push_syntax_node(SyntaxNode::new_close()),
-                        ];
-
-                        if let Some(name) = vtable_alias {
-                            if name.is_empty() {
-                                return Err(SbroadError::Invalid(
-                                    Entity::VirtualTable,
-                                    Some(format_smolstr!(
-                                        "Vtable {vtable:?} has an empty alias name"
-                                    )),
-                                ));
-                            }
-                            children.push(
-                                self.nodes
-                                    .push_syntax_node(SyntaxNode::new_alias(name.clone())),
-                            );
-                        }
-                        children
-                    } else {
-                        vec![self.nodes.push_syntax_node(SyntaxNode::new_vtable(id))]
-                    };
-
-                    let sn = SyntaxNode::new_pointer(id, None, children);
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::ValuesRow { data, .. } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        None,
-                        vec![self.nodes.get_syntax_node_id(*data)?],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Relational::Values { children, .. } => {
-                    let mut sn_children: Vec<usize> = Vec::with_capacity(children.len() * 2);
-                    if let Some((last_id, other)) = children.split_last() {
-                        for child_id in other {
-                            sn_children.push(self.nodes.get_syntax_node_id(*child_id)?);
-                            sn_children.push(self.nodes.push_syntax_node(SyntaxNode::new_comma()));
-                        }
-                        sn_children.push(self.nodes.get_syntax_node_id(*last_id)?);
-                    }
-
-                    let sn = SyntaxNode::new_pointer(id, None, sn_children);
-                    Ok(self.nodes.push_syntax_node(sn))
+                | Relational::Update { .. } => {
+                    panic!("DML node {node:?} is not supported in the syntax plan")
                 }
+                Relational::Join { .. } => self.add_join(id),
+                Relational::Projection { .. } => self.add_proj(id),
+                Relational::OrderBy { .. } => self.add_order_by(id),
+                Relational::ScanCte { .. } => self.add_cte(id),
+                Relational::ScanSubQuery { .. } => self.add_sq(id),
+                Relational::GroupBy { .. } => self.add_group_by(id),
+                Relational::Selection { .. } | Relational::Having { .. } => self.add_filter(id),
+                Relational::Except { .. }
+                | Relational::Union { .. }
+                | Relational::UnionAll { .. }
+                | Relational::Intersect { .. } => self.add_set(id),
+                Relational::ScanRelation { .. } => self.add_scan_relation(id),
+                Relational::Motion { .. } => self.add_motion(id),
+                Relational::ValuesRow { .. } => self.add_values_row(id),
+                Relational::Values { .. } => self.add_values(id),
             },
             Node::Expression(expr) => match expr {
-                Expression::ExprInParentheses { child } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.push_syntax_node(SyntaxNode::new_open())),
-                        vec![
-                            self.nodes.get_syntax_node_id(*child)?,
-                            self.nodes.push_syntax_node(SyntaxNode::new_close()),
-                        ],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Expression::Cast { child, to } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.push_syntax_node(SyntaxNode::new_cast())),
-                        vec![
-                            self.nodes.push_syntax_node(SyntaxNode::new_open()),
-                            self.nodes.get_syntax_node_id(*child)?,
-                            self.nodes
-                                .push_syntax_node(SyntaxNode::new_alias(SmolStr::from(to))),
-                            self.nodes.push_syntax_node(SyntaxNode::new_close()),
-                        ],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Expression::Concat { left, right } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(*left)?),
-                        vec![
-                            self.nodes.push_syntax_node(SyntaxNode::new_concat()),
-                            self.nodes.get_syntax_node_id(*right)?,
-                        ],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
+                Expression::ExprInParentheses { .. } => self.add_expr_in_parentheses(id),
+                Expression::Cast { .. } => self.add_cast(id),
+                Expression::Concat { .. } => self.add_concat(id),
                 Expression::Constant { .. } => {
                     let sn = SyntaxNode::new_parameter(id);
-                    Ok(self.nodes.push_syntax_node(sn))
+                    self.nodes.push_sn_plan(sn);
                 }
                 Expression::Reference { .. } | Expression::CountAsterisk => {
                     let sn = SyntaxNode::new_pointer(id, None, vec![]);
-                    Ok(self.nodes.push_syntax_node(sn))
+                    self.nodes.push_sn_plan(sn);
                 }
-                Expression::Alias { child, name, .. } => {
-                    // Do not generate an alias in SQL when a column has exactly the same name.
-                    let child_expr = ir_plan.get_expression_node(*child)?;
-                    if let Expression::Reference { .. } = child_expr {
-                        let alias = &ir_plan.get_alias_from_reference_node(child_expr)?;
-                        if alias == name {
-                            let sn = SyntaxNode::new_pointer(
-                                id,
-                                None,
-                                vec![self.nodes.get_syntax_node_id(*child)?],
-                            );
-                            return Ok(self.nodes.push_syntax_node(sn));
-                        }
-                    }
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(*child)?),
-                        vec![self
-                            .nodes
-                            .push_syntax_node(SyntaxNode::new_alias(name.clone()))],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
+                Expression::Alias { .. } => self.add_alias(id),
+                Expression::Row { .. } => self.add_row(id),
+                Expression::Bool { .. } | Expression::Arithmetic { .. } => self.add_binary_op(id),
+                Expression::Unary { .. } => self.add_unary_op(id),
+                Expression::StableFunction { .. } => self.add_stable_func(id),
+                Expression::Trim { .. } => self.add_trim(id),
+            },
+        }
+    }
+
+    fn prologue_rel(&self, id: usize) -> (&Plan, &Relational) {
+        let plan = self.plan.get_ir_plan();
+        let rel = plan
+            .get_relation_node(id)
+            .expect("node {id} must exist in the plan");
+        (plan, rel)
+    }
+
+    fn prologue_expr(&self, id: usize) -> (&Plan, &Expression) {
+        let plan = self.plan.get_ir_plan();
+        let expr = plan
+            .get_expression_node(id)
+            .expect("node {id} must exist in the plan");
+        (plan, expr)
+    }
+
+    // Relational nodes.
+
+    fn add_cte(&mut self, id: usize) {
+        let (_, cte) = self.prologue_rel(id);
+        let Relational::ScanCte { alias, child, .. } = cte else {
+            panic!("expected CTE node");
+        };
+        let (child, alias) = (*child, alias.clone());
+        let child_sn_id = self.pop_from_stack(child);
+        let arena = &mut self.nodes;
+        let children: Vec<usize> = vec![
+            arena.push_sn_non_plan(SyntaxNode::new_open()),
+            child_sn_id,
+            arena.push_sn_non_plan(SyntaxNode::new_close()),
+            arena.push_sn_non_plan(SyntaxNode::new_alias(alias)),
+        ];
+        let sn = SyntaxNode::new_pointer(id, None, children);
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_filter(&mut self, id: usize) {
+        let (plan, rel) = self.prologue_rel(id);
+        let (Relational::Selection {
+            children, filter, ..
+        }
+        | Relational::Having {
+            children, filter, ..
+        }) = rel
+        else {
+            panic!("Expected FILTER node");
+        };
+        let filter_id = match self.snapshot {
+            Snapshot::Latest => *filter,
+            Snapshot::Oldest => *plan.undo.get_oldest(filter).map_or_else(|| filter, |id| id),
+        };
+        let child_plan_id = *children.first().expect("FILTER child");
+        let filter_sn_id = self.pop_from_stack(filter_id);
+        let child_sn_id = self.pop_from_stack(child_plan_id);
+        let sn = SyntaxNode::new_pointer(id, Some(child_sn_id), vec![filter_sn_id]);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_group_by(&mut self, id: usize) {
+        let (_, gb) = self.prologue_rel(id);
+        let Relational::GroupBy {
+            children, gr_cols, ..
+        } = gb
+        else {
+            panic!("Expected GROUP BY node");
+        };
+        let child_plan_id = *children.first().expect("GROUP BY child");
+        // The columns on the stack are in reverse order.
+        let mut sn_gr_cols = gr_cols.iter().rev().copied().collect::<Vec<_>>();
+        // Reuse the same vector to avoid extra allocations
+        // (replace plan node ids with syntax node ids).
+        for col_id in &mut sn_gr_cols {
+            *col_id = self.pop_from_stack(*col_id);
+        }
+        let child_sn_id = self.pop_from_stack(child_plan_id);
+        let mut sn_children = Vec::with_capacity(sn_gr_cols.len() * 2 - 1);
+        // The columns are in reverse order, so we need to reverse them back.
+        if let Some((first, others)) = sn_gr_cols.split_first() {
+            for id in others.iter().rev() {
+                sn_children.push(*id);
+                sn_children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_comma()));
+            }
+            sn_children.push(*first);
+        }
+        let sn = SyntaxNode::new_pointer(id, Some(child_sn_id), sn_children);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_join(&mut self, id: usize) {
+        let (plan, join) = self.prologue_rel(id);
+        let Relational::Join {
+            children,
+            condition,
+            ..
+        } = join
+        else {
+            panic!("Expected JOIN node");
+        };
+        let cond_plan_id = match self.snapshot {
+            Snapshot::Latest => *condition,
+            Snapshot::Oldest => *plan
+                .undo
+                .get_oldest(condition)
+                .map_or_else(|| condition, |id| id),
+        };
+        let inner_plan_id = *children.get(1).expect("JOIN inner child");
+        let outer_plan_id = *children.first().expect("JOIN outer child");
+        let cond_sn_id = self.pop_from_stack(cond_plan_id);
+        let inner_sn_id = self.pop_from_stack(inner_plan_id);
+        let outer_sn_id = self.pop_from_stack(outer_plan_id);
+        let arena = &mut self.nodes;
+        let sn = SyntaxNode::new_pointer(
+            id,
+            Some(outer_sn_id),
+            vec![
+                inner_sn_id,
+                arena.push_sn_non_plan(SyntaxNode::new_condition()),
+                cond_sn_id,
+            ],
+        );
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_motion(&mut self, id: usize) {
+        let (plan, motion) = self.prologue_rel(id);
+        let Relational::Motion {
+            policy,
+            children,
+            is_child_subquery,
+            program,
+            output,
+            ..
+        } = motion
+        else {
+            panic!("Expected MOTION node");
+        };
+
+        let first_child = children.first().copied();
+        if let MotionPolicy::LocalSegment { .. } = policy {
+            #[cfg(feature = "mock")]
+            {
+                // We should materialize the subquery on the storage. Honestly, this SQL
+                // is not valid and should never be generated in runtime, but let's leave
+                // it for testing.
+                let child_plan_id = first_child.expect("MOTION child");
+                let child_sn_id = self.pop_from_stack(child_plan_id);
+                let sn = SyntaxNode::new_pointer(id, Some(child_sn_id), vec![]);
+                self.nodes.push_sn_plan(sn);
+                return;
+            }
+            #[cfg(not(feature = "mock"))]
+            {
+                panic!("Local segment notion policy is not supported in the syntax plan");
+            }
+        }
+
+        let empty_table_op = program
+            .0
+            .iter()
+            .find(|op| matches!(op, MotionOpcode::SerializeAsEmptyTable(_)));
+        if let Some(op) = empty_table_op {
+            let is_enabled = matches!(op, MotionOpcode::SerializeAsEmptyTable(true));
+            if is_enabled {
+                let output_cols = plan.get_row_list(*output).expect("row aliases");
+                // We need to preserve types when doing `select null`,
+                // otherwise tarantool will cast it to `scalar`.
+                let mut select_columns = Vec::with_capacity(output_cols.len());
+                for col in output_cols {
+                    let ref_id = plan
+                        .get_child_under_alias(*col)
+                        .expect("motion output must be a row of aliases!");
+                    let ref_expr = plan.get_expression_node(ref_id).expect("reference node");
+                    let Expression::Reference { col_type, .. } = ref_expr else {
+                        panic!("expected Reference under Alias in Motion output");
+                    };
+                    select_columns.push(format_smolstr!("cast(null as {col_type})"));
                 }
-                Expression::Row { list, .. } => {
-                    // In projections with a huge amount of columns it can be
-                    // very expensive to retrieve corresponding relational nodes.
-                    let rel_ids = ir_plan.get_relational_nodes_from_row(id)?;
-
-                    if let Some(motion_id) = ir_plan.get_motion_among_rel_nodes(&rel_ids)? {
-                        // Logic of replacing row child with vtable (corresponding to motion) is
-                        // applicable only in case the child is Reference appeared from transformed
-                        // SubQuery (Like in case `Exists` or `In` operator or in expression like
-                        // `select * from t where b = (select a from t)`).
-                        // There are other cases of row containing references to `Motion` nodes when
-                        // we shouldn't replace them with vtable (e.g. aggregates' stable functions
-                        // which arguments may point to `Motion` node).
-                        let first_child_id = *list.first().ok_or_else(|| {
-                            SbroadError::Invalid(
-                                Entity::Expression,
-                                Some(SmolStr::from("Row node should have child list node")),
-                            )
-                        })?;
-                        let first_child = ir_plan.get_expression_node(first_child_id)?;
-                        let first_child_is_ref =
-                            matches!(first_child, Expression::Reference { .. });
-
-                        // Replace motion node to virtual table node
-                        let vtable = self.plan.get_motion_vtable(motion_id)?;
-                        let needs_replacement = vtable.get_alias().is_none()
-                            && first_child_is_ref
-                            && ir_plan.is_additional_child(motion_id)?;
-                        if needs_replacement {
-                            let sn = SyntaxNode::new_pointer(
-                                id,
-                                None,
-                                vec![
-                                    self.nodes.push_syntax_node(SyntaxNode::new_open()),
-                                    self.nodes
-                                        .push_syntax_node(SyntaxNode::new_vtable(motion_id)),
-                                    self.nodes.push_syntax_node(SyntaxNode::new_close()),
-                                ],
-                            );
-
-                            return Ok(self.nodes.push_syntax_node(sn));
-                        }
-                    }
+                let empty_select =
+                    format_smolstr!("select {} where false", select_columns.join(","));
+                let inline = SyntaxNode::new_inline(&empty_select);
+                let inline_sn_id = self.nodes.push_sn_non_plan(inline);
+                let sn = SyntaxNode::new_pointer(id, None, vec![inline_sn_id]);
+                self.nodes.push_sn_plan(sn);
+            }
+            return;
+        }
+        let vtable = self
+            .plan
+            .get_motion_vtable(id)
+            .expect("motion virtual table");
 
-                    if let Some(sq_id) = ir_plan.get_sub_query_among_rel_nodes(&rel_ids)? {
-                        // Replace current row with the referred sub-query
-                        // (except the case when sub-query is located in the FROM clause).
-                        if ir_plan.is_additional_child(sq_id)? {
-                            let rel = ir_plan.get_relation_node(sq_id)?;
-                            return self.nodes.add_sq(rel, id);
-                        }
+        let vtable_alias = vtable.get_alias().cloned();
+        let is_child_subquery = *is_child_subquery;
+
+        // Remove motion's child from the stack (if any).
+        if let Some(child_id) = first_child {
+            let _ = self.pop_from_stack(child_id);
+        }
+
+        let arena = &mut self.nodes;
+
+        // There are some cases when motion child is not a `SubQuery` and when
+        // it has an alias. E.g. in case of a `INSERT ... SELECT ...` its child
+        // may be a `Projection`.
+        let sn_children = if is_child_subquery || vtable_alias.is_some() {
+            let mut children: Vec<usize> = vec![
+                arena.push_sn_non_plan(SyntaxNode::new_open()),
+                arena.push_sn_non_plan(SyntaxNode::new_vtable(id)),
+                arena.push_sn_non_plan(SyntaxNode::new_close()),
+            ];
+
+            if let Some(name) = vtable_alias {
+                assert!(
+                    !name.is_empty(),
+                    "Virtual table {vtable:?} has an empty alias name"
+                );
+                let alias = SyntaxNode::new_alias(name);
+                children.push(arena.push_sn_non_plan(alias));
+            }
+            children
+        } else {
+            vec![arena.push_sn_non_plan(SyntaxNode::new_vtable(id))]
+        };
+
+        let sn = SyntaxNode::new_pointer(id, None, sn_children);
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_order_by(&mut self, id: usize) {
+        let (_, order_by) = self.prologue_rel(id);
+        let Relational::OrderBy {
+            order_by_elements,
+            child,
+            ..
+        } = order_by
+        else {
+            panic!("expect ORDER BY node");
+        };
+        let child_plan_id = *child;
+        let mut elems = order_by_elements.clone();
+
+        let mut children: Vec<usize> = Vec::with_capacity(elems.len() * 3 - 1);
+        let mut wrapped_syntax_nodes =
+            |elem: &OrderByElement, need_comma: bool| -> [Option<usize>; 3] {
+                let mut nodes = [None, None, None];
+                match elem.entity {
+                    OrderByEntity::Expression { expr_id } => {
+                        let expr_sn_id = self.pop_from_stack(expr_id);
+                        nodes[2] = Some(expr_sn_id);
                     }
-                    let mut nodes: Vec<usize> =
-                        vec![self.nodes.push_syntax_node(SyntaxNode::new_open())];
-                    if let Some((last, elements)) = list.split_last() {
-                        nodes.reserve(list.len() * 2);
-                        for elem in elements {
-                            nodes.push(self.nodes.get_syntax_node_id(*elem)?);
-                            nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_comma()));
-                        }
-                        nodes.push(self.nodes.get_syntax_node_id(*last)?);
-                        nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_close()));
-                        let sn = SyntaxNode::new_pointer(id, None, nodes);
-                        return Ok(self.nodes.push_syntax_node(sn));
+                    OrderByEntity::Index { value } => {
+                        let sn = SyntaxNode::new_order_index(value);
+                        nodes[2] = Some(self.nodes.push_sn_non_plan(sn));
                     }
-                    Err(SbroadError::Invalid(Entity::Expression, None))
                 }
-                Expression::Bool {
-                    left, right, op, ..
-                } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(*left)?),
-                        vec![
-                            self.nodes
-                                .push_syntax_node(SyntaxNode::new_operator(&format!("{op}"))),
-                            self.nodes.get_syntax_node_id(*right)?,
-                        ],
-                    );
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Expression::Arithmetic { left, right, op } => {
-                    let sn = SyntaxNode::new_pointer(
-                        id,
-                        Some(self.nodes.get_syntax_node_id(*left)?),
-                        vec![
-                            self.nodes
-                                .push_syntax_node(SyntaxNode::new_operator(&format!("{op}"))),
-                            self.nodes.get_syntax_node_id(*right)?,
-                        ],
-                    );
-
-                    Ok(self.nodes.push_syntax_node(sn))
+                if let Some(order_type) = &elem.order_type {
+                    let sn = SyntaxNode::new_order_type(order_type);
+                    nodes[1] = Some(self.nodes.push_sn_non_plan(sn));
                 }
-                Expression::Unary { child, op, .. } => {
-                    let operator_node_id = self
-                        .nodes
-                        .push_syntax_node(SyntaxNode::new_operator(&format!("{op}")));
-                    let child_node_id = self.nodes.get_syntax_node_id(*child)?;
-                    let child_node = ir_plan.get_expression_node(*child)?;
-                    // Bool::Or operator already covers itself with parentheses, that's why we
-                    // don't have to cover it here.
-                    let sn = if *op == Unary::Not
-                        && matches!(*child_node, Expression::Bool { op: Bool::And, .. })
-                    {
-                        SyntaxNode::new_pointer(
-                            id,
-                            Some(operator_node_id),
-                            vec![
-                                self.nodes.push_syntax_node(SyntaxNode::new_open()),
-                                child_node_id,
-                                self.nodes.push_syntax_node(SyntaxNode::new_close()),
-                            ],
-                        )
-                    } else {
-                        let (left, right) = match op {
-                            Unary::IsNull => (child_node_id, operator_node_id),
-                            Unary::Exists | Unary::Not => (operator_node_id, child_node_id),
-                        };
-                        SyntaxNode::new_pointer(id, Some(left), vec![right])
-                    };
-                    Ok(self.nodes.push_syntax_node(sn))
+                if need_comma {
+                    nodes[0] = Some(self.nodes.push_sn_non_plan(SyntaxNode::new_comma()));
                 }
-                Expression::StableFunction {
-                    children, feature, ..
-                } => {
-                    let mut nodes: Vec<usize> =
-                        vec![self.nodes.push_syntax_node(SyntaxNode::new_open())];
-                    if let Some(FunctionFeature::Distinct) = feature {
-                        nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_distinct()));
-                    }
-                    if let Some((last, others)) = children.split_last() {
-                        for child in others {
-                            nodes.push(self.nodes.get_syntax_node_id(*child)?);
-                            nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_comma()));
-                        }
-                        nodes.push(self.nodes.get_syntax_node_id(*last)?);
-                    }
+                nodes
+            };
 
-                    nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_close()));
-                    let sn = SyntaxNode::new_pointer(id, None, nodes);
-                    Ok(self.nodes.push_syntax_node(sn))
-                }
-                Expression::Trim {
-                    kind,
-                    pattern,
-                    target,
-                } => {
-                    let syn_kind = match kind {
-                        Some(TrimKind::Leading) => Some(SyntaxNode::new_leading()),
-                        Some(TrimKind::Trailing) => Some(SyntaxNode::new_trailing()),
-                        Some(TrimKind::Both) => Some(SyntaxNode::new_both()),
-                        None => None,
-                    };
-                    let mut nodes = Vec::with_capacity(6);
-                    nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_open()));
-                    let mut need_from = false;
-                    if let Some(kind) = syn_kind {
-                        nodes.push(self.nodes.push_syntax_node(kind));
-                        need_from = true;
-                    }
-                    if let Some(pattern) = pattern {
-                        nodes.push(self.nodes.get_syntax_node_id(*pattern)?);
-                        need_from = true;
-                    }
-                    if need_from {
-                        nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_from()));
+        // The elements on the stack are in the reverse order.
+        let first = elems.pop().expect("at least one column in ORDER BY");
+        for id in wrapped_syntax_nodes(&first, false).into_iter().flatten() {
+            children.push(id);
+        }
+        while let Some(elem) = elems.pop() {
+            for id in wrapped_syntax_nodes(&elem, true).into_iter().flatten() {
+                children.push(id);
+            }
+        }
+        // Reverse the order of the children back.
+        children.reverse();
+
+        let child_sn_id = self.pop_from_stack(child_plan_id);
+
+        let sn = SyntaxNode::new_pointer(id, Some(child_sn_id), children);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_proj(&mut self, id: usize) {
+        let (_, proj) = self.prologue_rel(id);
+        let Relational::Projection {
+            children, output, ..
+        } = proj
+        else {
+            panic!("Expected PROJECTION node");
+        };
+        let child_plan_id = *children.first().expect("PROJECTION child");
+        let output = *output;
+        let child_sn_id = self.pop_from_stack(child_plan_id);
+        let row_sn_id = self.pop_from_stack(output);
+        // We don't need the row node itself, only its children. Otherwise we'll produce
+        // redundant parentheses between `SELECT` and `FROM`.
+        let sn_from_id = self.nodes.push_sn_non_plan(SyntaxNode::new_from());
+        let row_sn = self.nodes.get_mut_sn(row_sn_id);
+        let col_len = row_sn.right.len();
+        let mut children = Vec::with_capacity(col_len - 1);
+        // Remove the open and close parentheses.
+        for (pos, id) in row_sn.right.iter().enumerate() {
+            if pos == 0 {
+                continue;
+            }
+            if pos == col_len - 1 {
+                children.push(sn_from_id);
+                break;
+            }
+            children.push(*id);
+        }
+        let sn = SyntaxNode::new_pointer(id, Some(child_sn_id), children);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_scan_relation(&mut self, id: usize) {
+        let (_, scan) = self.prologue_rel(id);
+        let Relational::ScanRelation { alias, .. } = scan else {
+            panic!("Expected SCAN node");
+        };
+        let scan_alias = alias.clone();
+        let arena = &mut self.nodes;
+        let children = if let Some(name) = scan_alias {
+            vec![arena.push_sn_non_plan(SyntaxNode::new_alias(name))]
+        } else {
+            Vec::new()
+        };
+        let sn = SyntaxNode::new_pointer(id, None, children);
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_set(&mut self, id: usize) {
+        let (_, set) = self.prologue_rel(id);
+        let (Relational::Except { left, right, .. }
+        | Relational::Union { left, right, .. }
+        | Relational::UnionAll { left, right, .. }
+        | Relational::Intersect { left, right, .. }) = set
+        else {
+            panic!("Expected SET node");
+        };
+        let (left, right) = (*left, *right);
+        let right_sn_id = self.pop_from_stack(right);
+        let left_sn_id = self.pop_from_stack(left);
+        let sn = SyntaxNode::new_pointer(id, Some(left_sn_id), vec![right_sn_id]);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_sq(&mut self, id: usize) {
+        let (_, sq) = self.prologue_rel(id);
+        let Relational::ScanSubQuery {
+            children, alias, ..
+        } = sq
+        else {
+            panic!("Expected SUBQUERY node");
+        };
+        let child_plan_id = *children.first().expect("SUBQUERY child");
+        let sq_alias = alias.clone();
+        let child_sn_id = self.pop_from_stack(child_plan_id);
+
+        let arena = &mut self.nodes;
+        let mut children: Vec<usize> = vec![
+            arena.push_sn_non_plan(SyntaxNode::new_open()),
+            child_sn_id,
+            arena.push_sn_non_plan(SyntaxNode::new_close()),
+        ];
+        if let Some(name) = sq_alias {
+            children.push(arena.push_sn_non_plan(SyntaxNode::new_alias(name)));
+        }
+        let sn = SyntaxNode::new_pointer(id, None, children);
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_values_row(&mut self, id: usize) {
+        let (_, row) = self.prologue_rel(id);
+        let Relational::ValuesRow { data, .. } = row else {
+            panic!("Expected VALUES ROW node");
+        };
+        let data_sn_id = self.pop_from_stack(*data);
+        let sn = SyntaxNode::new_pointer(id, None, vec![data_sn_id]);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_values(&mut self, id: usize) {
+        let (_, values) = self.prologue_rel(id);
+        let Relational::Values {
+            children, output, ..
+        } = values
+        else {
+            panic!("Expected VALUES node");
+        };
+        let output_plan_id = *output;
+        // The syntax nodes on the stack are in the reverse order.
+        let mut sn_children = children.iter().rev().copied().collect::<Vec<_>>();
+        // Reuse the same vector to avoid extra allocations (replace plan node ids with syntax node ids).
+        for child_id in &mut sn_children {
+            *child_id = self.pop_from_stack(*child_id);
+        }
+        let mut nodes = Vec::with_capacity(sn_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.
+        let _ = self.pop_from_stack(output_plan_id);
+
+        let arena = &mut self.nodes;
+        while let Some(child_id) = sn_children.pop() {
+            nodes.push(child_id);
+            nodes.push(arena.push_sn_non_plan(SyntaxNode::new_comma()));
+        }
+        nodes.push(first);
+        let sn = SyntaxNode::new_pointer(id, None, nodes);
+        arena.push_sn_plan(sn);
+    }
+
+    // Expression nodes.
+
+    fn add_alias(&mut self, id: usize) {
+        let (_, expr) = self.prologue_expr(id);
+        let Expression::Alias { child, name } = expr else {
+            panic!("Expected ALIAS node");
+        };
+        let (child, name) = (*child, name.clone());
+        let child_sn_id = self.pop_from_stack(child);
+        let plan = self.plan.get_ir_plan();
+        // Do not generate an alias in SQL when a column has exactly the same name.
+        let child_expr = plan
+            .get_expression_node(child)
+            .expect("alias child expression");
+        if let Expression::Reference { .. } = child_expr {
+            let alias = plan
+                .get_alias_from_reference_node(child_expr)
+                .expect("alias name");
+            if alias == name {
+                let sn = SyntaxNode::new_pointer(id, None, vec![child_sn_id]);
+                self.nodes.push_sn_plan(sn);
+                return;
+            }
+        }
+        let alias_sn_id = self.nodes.push_sn_non_plan(SyntaxNode::new_alias(name));
+        let sn = SyntaxNode::new_pointer(id, Some(child_sn_id), vec![alias_sn_id]);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_binary_op(&mut self, id: usize) {
+        let (_, expr) = self.prologue_expr(id);
+        let (left_plan_id, right_plan_id, op_sn_id) = match expr {
+            Expression::Bool {
+                left, right, op, ..
+            } => {
+                let (op, left, right) = (op.clone(), *left, *right);
+                let op_sn_id = self
+                    .nodes
+                    .push_sn_non_plan(SyntaxNode::new_operator(&format!("{op}")));
+                (left, right, op_sn_id)
+            }
+            Expression::Arithmetic {
+                left, right, op, ..
+            } => {
+                let (op, left, right) = (op.clone(), *left, *right);
+                let op_sn_id = self
+                    .nodes
+                    .push_sn_non_plan(SyntaxNode::new_operator(&format!("{op}")));
+                (left, right, op_sn_id)
+            }
+            _ => panic!("Expected binary expression node"),
+        };
+        let right_sn_id = self.pop_from_stack(right_plan_id);
+        let left_sn_id = self.pop_from_stack(left_plan_id);
+        let children = vec![op_sn_id, right_sn_id];
+        let sn = SyntaxNode::new_pointer(id, Some(left_sn_id), children);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_cast(&mut self, id: usize) {
+        let (_, expr) = self.prologue_expr(id);
+        let Expression::Cast { child, to } = expr else {
+            panic!("Expected CAST node");
+        };
+        let to_alias = SmolStr::from(to);
+        let child_plan_id = *child;
+        let child_sn_id = self.pop_from_stack(child_plan_id);
+        let arena = &mut self.nodes;
+        let children = vec![
+            arena.push_sn_non_plan(SyntaxNode::new_open()),
+            child_sn_id,
+            arena.push_sn_non_plan(SyntaxNode::new_alias(to_alias)),
+            arena.push_sn_non_plan(SyntaxNode::new_close()),
+        ];
+        let cast_sn_id = arena.push_sn_non_plan(SyntaxNode::new_cast());
+        let sn = SyntaxNode::new_pointer(id, Some(cast_sn_id), children);
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_concat(&mut self, id: usize) {
+        let (_, expr) = self.prologue_expr(id);
+        let Expression::Concat { left, right } = expr else {
+            panic!("Expected CONCAT node");
+        };
+        let (left, right) = (*left, *right);
+        let right_sn_id = self.pop_from_stack(right);
+        let left_sn_id = self.pop_from_stack(left);
+        let children = vec![
+            self.nodes.push_sn_non_plan(SyntaxNode::new_concat()),
+            right_sn_id,
+        ];
+        let sn = SyntaxNode::new_pointer(id, Some(left_sn_id), children);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_expr_in_parentheses(&mut self, id: usize) {
+        let (_, expr) = self.prologue_expr(id);
+        let Expression::ExprInParentheses { child } = expr else {
+            panic!("Expected expression in parentheses node");
+        };
+        let child_sn_id = self.pop_from_stack(*child);
+        let arena = &mut self.nodes;
+        let children = vec![child_sn_id, arena.push_sn_non_plan(SyntaxNode::new_close())];
+        let sn = SyntaxNode::new_pointer(
+            id,
+            Some(arena.push_sn_non_plan(SyntaxNode::new_open())),
+            children,
+        );
+        arena.push_sn_plan(sn);
+    }
+
+    fn add_row(&mut self, id: usize) {
+        let plan = self.plan.get_ir_plan();
+        let expr = plan
+            .get_expression_node(id)
+            .expect("node {id} must exist in the plan");
+        let Expression::Row { list, .. } = expr else {
+            panic!("Expected ROW node");
+        };
+
+        // In projections with a huge amount of columns it can be
+        // very expensive to retrieve corresponding relational nodes.
+        let rel_ids = plan
+            .get_relational_nodes_from_row(id)
+            .expect("row relational nodes");
+
+        if let Some(motion_id) = plan
+            .get_motion_among_rel_nodes(&rel_ids)
+            .expect("motion lookup")
+        {
+            // Logic of replacing row child with vtable (corresponding to motion) is
+            // applicable only in case the child is Reference appeared from transformed
+            // SubQuery (Like in case `Exists` or `In` operator or in expression like
+            // `select * from t where b = (select a from t)`).
+            // There are other cases of row containing references to `Motion` nodes when
+            // we shouldn't replace them with vtable (e.g. aggregates' stable functions
+            // which arguments may point to `Motion` node).
+            let first_child_id = *list.first().expect("row should have at least one child");
+            let first_child = plan
+                .get_expression_node(first_child_id)
+                .expect("row child is expression");
+            let first_child_is_ref = matches!(first_child, Expression::Reference { .. });
+
+            // Replace motion node to virtual table node.
+            let vtable = self
+                .plan
+                .get_motion_vtable(motion_id)
+                .expect("motion virtual table");
+            let needs_replacement = vtable.get_alias().is_none()
+                && first_child_is_ref
+                && plan
+                    .is_additional_child(motion_id)
+                    .expect("motion id is valid");
+            if needs_replacement {
+                // Remove columns from the stack.
+                for child_id in list.iter().rev() {
+                    let _ = self.pop_from_stack(*child_id);
+
+                    // Remove the referred motion from the stack (if any).
+                    let expr = plan
+                        .get_expression_node(*child_id)
+                        .expect("row child is expression");
+                    if matches!(expr, Expression::Reference { .. }) {
+                        let referred_id = *plan
+                            .get_relational_from_reference_node(*child_id)
+                            .expect("referred id");
+                        self.pop_from_stack(referred_id);
                     }
-                    nodes.push(self.nodes.get_syntax_node_id(*target)?);
-                    nodes.push(self.nodes.push_syntax_node(SyntaxNode::new_close()));
+                }
+
+                // Add virtual table node to the stack.
+                let arena = &mut self.nodes;
+                let children = vec![
+                    arena.push_sn_non_plan(SyntaxNode::new_open()),
+                    arena.push_sn_non_plan(SyntaxNode::new_vtable(motion_id)),
+                    arena.push_sn_non_plan(SyntaxNode::new_close()),
+                ];
+                let sn = SyntaxNode::new_pointer(id, None, children);
+                arena.push_sn_plan(sn);
+                return;
+            }
+        }
 
-                    let trim_id = self.nodes.push_syntax_node(SyntaxNode::new_trim());
-                    let sn = SyntaxNode::new_pointer(id, Some(trim_id), nodes);
-                    Ok(self.nodes.push_syntax_node(sn))
+        if let Some(sq_id) = plan
+            .get_sub_query_among_rel_nodes(&rel_ids)
+            .expect("subquery id")
+        {
+            // Replace current row with the referred sub-query
+            // (except the case when sub-query is located in the FROM clause).
+            if plan
+                .is_additional_child(sq_id)
+                .expect("subquery id is valid")
+            {
+                let mut sq_sn_id = None;
+
+                // Remove columns from the stack.
+                for child_id in list.iter().rev() {
+                    let _ = self.pop_from_stack(*child_id);
+
+                    // Remove the referred sub-query from the stack (if any).
+                    let expr = plan
+                        .get_expression_node(*child_id)
+                        .expect("row child is expression");
+                    if matches!(expr, Expression::Reference { .. }) {
+                        let referred_id = *plan
+                            .get_relational_from_reference_node(*child_id)
+                            .expect("referred id");
+                        sq_sn_id = Some(self.pop_from_stack(referred_id));
+                    }
                 }
-            },
+
+                // Restore the sub-query node on the top of the stack.
+                self.push_on_stack(sq_sn_id.expect("sub-query id"));
+
+                return;
+            }
         }
+
+        let mut children = Vec::with_capacity(list.len() * 2 + 3);
+        // The nodes on the stack are in the reverse order.
+        children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_close()));
+        if let Some((first, others)) = list.split_first() {
+            for child_id in others.iter().rev() {
+                children.push(self.pop_from_stack(*child_id));
+                children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_comma()));
+            }
+            children.push(self.pop_from_stack(*first));
+        }
+        children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_open()));
+        // Need to reverse the order of the children back.
+        children.reverse();
+        let sn = SyntaxNode::new_pointer(id, None, children);
+        self.nodes.push_sn_plan(sn);
     }
 
-    /// Get the plan node from the syntax tree node.
+    fn add_stable_func(&mut self, id: usize) {
+        let plan = self.plan.get_ir_plan();
+        let expr = plan
+            .get_expression_node(id)
+            .expect("node {id} must exist in the plan");
+        let Expression::StableFunction {
+            children: args,
+            feature,
+            ..
+        } = expr
+        else {
+            panic!("Expected stable function node");
+        };
+        // The arguments on the stack are in the reverse order.
+        let mut nodes = Vec::with_capacity(args.len() * 2 + 2);
+        nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_close()));
+        if let Some((first, others)) = args.split_first() {
+            for child_id in others.iter().rev() {
+                nodes.push(self.pop_from_stack(*child_id));
+                nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_comma()));
+            }
+            nodes.push(self.pop_from_stack(*first));
+        }
+        if let Some(FunctionFeature::Distinct) = feature {
+            nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_distinct()));
+        }
+        nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_open()));
+        // Need to reverse the order of the children back.
+        nodes.reverse();
+        let sn = SyntaxNode::new_pointer(id, None, nodes);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_trim(&mut self, id: usize) {
+        let (_, expr) = self.prologue_expr(id);
+        let Expression::Trim {
+            kind,
+            pattern,
+            target,
+        } = expr
+        else {
+            panic!("Expected TRIM node");
+        };
+        let (kind, pattern, target) = (kind.clone(), *pattern, *target);
+        let mut need_from = false;
+
+        // Syntax nodes on the stack are in the reverse order.
+        let target_sn_id = self.pop_from_stack(target);
+        let mut pattern_sn_id = None;
+        if let Some(pattern) = pattern {
+            pattern_sn_id = Some(self.pop_from_stack(pattern));
+            need_from = true;
+        }
+
+        // Populate trim children.
+        let sn_kind = match kind {
+            Some(TrimKind::Leading) => Some(SyntaxNode::new_leading()),
+            Some(TrimKind::Trailing) => Some(SyntaxNode::new_trailing()),
+            Some(TrimKind::Both) => Some(SyntaxNode::new_both()),
+            None => None,
+        };
+        let mut nodes = Vec::with_capacity(6);
+        nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_open()));
+        if let Some(kind) = sn_kind {
+            nodes.push(self.nodes.push_sn_non_plan(kind));
+            need_from = true;
+        }
+        if let Some(pattern) = pattern_sn_id {
+            nodes.push(pattern);
+        }
+        if need_from {
+            nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_from()));
+        }
+        nodes.push(target_sn_id);
+        nodes.push(self.nodes.push_sn_non_plan(SyntaxNode::new_close()));
+
+        let trim_id = self.nodes.push_sn_non_plan(SyntaxNode::new_trim());
+        let sn = SyntaxNode::new_pointer(id, Some(trim_id), nodes);
+        self.nodes.push_sn_plan(sn);
+    }
+
+    fn add_unary_op(&mut self, id: usize) {
+        let (plan, expr) = self.prologue_expr(id);
+        let Expression::Unary { child, op } = expr else {
+            panic!("Expected unary expression node");
+        };
+        let (child, op) = (*child, op.clone());
+        let child_node = plan.get_expression_node(child).expect("child expression");
+        let is_and = matches!(child_node, Expression::Bool { op: Bool::And, .. });
+        let operator_node_id = self
+            .nodes
+            .push_sn_non_plan(SyntaxNode::new_operator(&format!("{op}")));
+        let child_sn_id = self.pop_from_stack(child);
+        // Bool::Or operator already covers itself with parentheses, that's why we
+        // don't have to cover it here.
+        let sn = if op == Unary::Not && is_and {
+            SyntaxNode::new_pointer(
+                id,
+                Some(operator_node_id),
+                vec![
+                    self.nodes.push_sn_non_plan(SyntaxNode::new_open()),
+                    child_sn_id,
+                    self.nodes.push_sn_non_plan(SyntaxNode::new_close()),
+                ],
+            )
+        } else {
+            let (left, right) = match op {
+                Unary::IsNull => (child_sn_id, operator_node_id),
+                Unary::Exists | Unary::Not => (operator_node_id, child_sn_id),
+            };
+            SyntaxNode::new_pointer(id, Some(left), vec![right])
+        };
+        self.nodes.push_sn_plan(sn);
+    }
+
+    /// Get the plan node if any.
     ///
     /// # Errors
-    /// - plan node is invalid
+    /// - syntax node wraps an invalid plan node
     pub fn get_plan_node(&self, data: &SyntaxData) -> Result<Option<&Node>, SbroadError> {
         if let SyntaxData::PlanId(id) = data {
             Ok(Some(self.plan.get_ir_plan().get_node(*id)?))
@@ -1192,7 +1393,7 @@ impl<'p> SyntaxPlan<'p> {
     /// # Errors
     /// - top is invalid node
     pub fn set_top(&mut self, top: usize) -> Result<(), SbroadError> {
-        self.nodes.get_syntax_node(top)?;
+        self.nodes.get_sn(top);
         self.top = Some(top);
         Ok(())
     }
@@ -1204,7 +1405,7 @@ impl<'p> SyntaxPlan<'p> {
     /// - top is not a valid node
     pub fn get_top(&self) -> Result<usize, SbroadError> {
         if let Some(top) = self.top {
-            self.nodes.get_syntax_node(top)?;
+            self.nodes.get_sn(top);
             Ok(top)
         } else {
             Err(SbroadError::Invalid(
@@ -1229,7 +1430,7 @@ impl<'p> SyntaxPlan<'p> {
         dfs.populate_nodes(top);
         let nodes = dfs.take_nodes();
         for (_, pos) in nodes {
-            let node = self.nodes.get_syntax_node(pos)?;
+            let node = self.nodes.get_sn(pos);
             if pos == top {
                 let select = Select::new(self, None, None, pos)?;
                 if let Some(s) = select {
@@ -1304,7 +1505,8 @@ impl<'p> SyntaxPlan<'p> {
                     PostOrder::with_capacity(|node| ir_plan.subtree_iter(node, false), capacity);
                 for (_, id) in dft_post.iter(top) {
                     // it works only for post-order traversal
-                    let sn_id = sp.add_plan_node(id)?;
+                    sp.add_plan_node(id);
+                    let sn_id = sp.nodes.next_id() - 1;
                     if id == top {
                         sp.set_top(sn_id)?;
                     }
@@ -1315,7 +1517,8 @@ impl<'p> SyntaxPlan<'p> {
                     PostOrder::with_capacity(|node| ir_plan.flashback_subtree_iter(node), capacity);
                 for (_, id) in dft_post.iter(top) {
                     // it works only for post-order traversal
-                    let sn_id = sp.add_plan_node(id)?;
+                    sp.add_plan_node(id);
+                    let sn_id = sp.nodes.next_id() - 1;
                     if id == top {
                         sp.set_top(sn_id)?;
                     }
@@ -1328,7 +1531,7 @@ impl<'p> SyntaxPlan<'p> {
 
     fn reorder(&mut self, select: &Select) -> Result<(), SbroadError> {
         // Move projection under scan.
-        let proj = self.nodes.get_mut_syntax_node(select.proj)?;
+        let proj = self.nodes.get_mut_sn(select.proj);
         let new_top = proj.left.ok_or_else(|| {
             SbroadError::Invalid(
                 Entity::SyntaxPlan,
@@ -1336,12 +1539,12 @@ impl<'p> SyntaxPlan<'p> {
             )
         })?;
         proj.left = None;
-        let scan = self.nodes.get_mut_syntax_node(select.scan)?;
+        let scan = self.nodes.get_mut_sn(select.scan);
         scan.left = Some(select.proj);
 
         // Try to move new top under parent.
         if let Some(id) = select.parent {
-            let parent = self.nodes.get_mut_syntax_node(id)?;
+            let parent = self.nodes.get_mut_sn(id);
             match select.branch {
                 Some(Branch::Left) => {
                     parent.left = Some(new_top);
@@ -1438,13 +1641,13 @@ impl TryFrom<SyntaxPlan<'_>> for OrderedSyntaxNodes {
         // approach in Rust (`take()` and `pop()`).
         stack.push(sp.get_top()?);
         while let Some(id) = stack.last() {
-            let sn = sp.nodes.get_mut_syntax_node(*id)?;
+            let sn = sp.nodes.get_mut_sn(*id);
             // Note that in case `left` is a `Some(...)`, call of `take` will make it None.
             if let Some(left_id) = sn.left.take() {
                 stack.push(left_id);
             } else if let Some(id) = stack.pop() {
                 positions.push(id);
-                let sn_next = sp.nodes.get_mut_syntax_node(id)?;
+                let sn_next = sp.nodes.get_mut_sn(id);
                 while let Some(right_id) = sn_next.right.pop() {
                     stack.push(right_id);
                 }
diff --git a/sbroad-core/src/backend/sql/tree/tests.rs b/sbroad-core/src/backend/sql/tree/tests.rs
index b4b225d70..630548633 100644
--- a/sbroad-core/src/backend/sql/tree/tests.rs
+++ b/sbroad-core/src/backend/sql/tree/tests.rs
@@ -64,7 +64,7 @@ fn sql_order_selection() {
         .join("tree")
         .join("sql_order_selection_syntax_nodes.yaml");
     let s = fs::read_to_string(path).unwrap();
-    let expected_syntax_nodes = SyntaxNodes::from_yaml(&s).unwrap();
+    let expected_syntax_nodes: SyntaxNodes = serde_yaml::from_str(&s).unwrap();
     assert_eq!(expected_syntax_nodes, sp.nodes);
 
     let exec_plan = ExecutionPlan::from(plan);
diff --git a/sbroad-core/src/executor/ir.rs b/sbroad-core/src/executor/ir.rs
index c99993bb6..e0c5f8b1e 100644
--- a/sbroad-core/src/executor/ir.rs
+++ b/sbroad-core/src/executor/ir.rs
@@ -1,7 +1,7 @@
 use std::collections::HashMap;
 use std::rc::Rc;
 
-use ahash::AHashMap;
+use ahash::{AHashMap, AHashSet};
 use serde::{Deserialize, Serialize};
 use smol_str::{format_smolstr, SmolStr, ToSmolStr};
 
@@ -376,6 +376,29 @@ impl ExecutionPlan {
         subtree.populate_nodes(top_id);
         let nodes = subtree.take_nodes();
 
+        // We can't replace CTE subtree as it can be reused in other slices of the plan.
+        // So, collect all CTE nodes and their subtree nodes (relational and expression)
+        // as a set to avoid their removal.
+        let cte_id_iter = nodes.iter().map(|(_, id)| *id).filter(|id| {
+            matches!(
+                plan.get_node(*id),
+                Ok(Node::Relational(Relational::ScanCte { .. }))
+            )
+        });
+        let mut cte_ids: AHashSet<usize> = AHashSet::new();
+        let mut is_reserved = false;
+        for cte_id in cte_id_iter {
+            if !is_reserved {
+                is_reserved = true;
+                cte_ids.reserve(nodes.len());
+            }
+            let mut cte_subtree =
+                PostOrder::with_capacity(|node| plan.exec_plan_subtree_iter(node), nodes.len());
+            for (_, id) in cte_subtree.iter(cte_id) {
+                cte_ids.insert(id);
+            }
+        }
+
         // Translates the original plan's node id to the new sub-plan one.
         let mut translation: AHashMap<usize, usize> = AHashMap::with_capacity(nodes.len());
         let vtables_capacity = self.get_vtables().map_or_else(|| 1, HashMap::len);
@@ -398,7 +421,11 @@ impl ExecutionPlan {
 
             // Replace the node with some invalid value.
             // TODO: introduce some new enum variant for this purpose.
-            let mut node: Node = std::mem::replace(dst_node, Node::Parameter);
+            let mut node: Node = if cte_ids.contains(&node_id) {
+                dst_node.clone()
+            } else {
+                std::mem::replace(dst_node, Node::Parameter)
+            };
             let ir_plan = self.get_ir_plan();
             match node {
                 Node::Relational(ref mut rel) => {
diff --git a/sbroad-core/src/executor/tests/exec_plan.rs b/sbroad-core/src/executor/tests/exec_plan.rs
index 23b7ec4db..5a783aadc 100644
--- a/sbroad-core/src/executor/tests/exec_plan.rs
+++ b/sbroad-core/src/executor/tests/exec_plan.rs
@@ -800,7 +800,10 @@ fn global_table_scan() {
     assert_eq!(
         sql,
         PatternWithParams::new(
-            r#"SELECT "global_t"."a", "global_t"."b" FROM "global_t""#.to_string(),
+            format!(
+                "{}",
+                r#"SELECT "global_t"."a", "global_t"."b" FROM "global_t""#,
+            ),
             vec![]
         )
     );
@@ -1141,7 +1144,7 @@ fn global_except() {
         .unwrap();
     let mut expected = ProducerResult::new();
     expected.rows.extend(vec![vec![
-        LuaValue::String("Execute query locally".to_string()),
+        LuaValue::String(format!("Execute query locally")),
         LuaValue::String(String::from(PatternWithParams::new(
             r#"SELECT "global_t"."a" FROM "global_t" EXCEPT SELECT "e" FROM "TMP_test_47""#.into(),
             vec![],
diff --git a/sbroad-core/src/frontend/sql/ir/tests/cte.rs b/sbroad-core/src/frontend/sql/ir/tests/cte.rs
index edeeec711..6a85fc21d 100644
--- a/sbroad-core/src/frontend/sql/ir/tests/cte.rs
+++ b/sbroad-core/src/frontend/sql/ir/tests/cte.rs
@@ -80,7 +80,6 @@ fn reuse_cte() {
         SELECT * FROM cte
     "#;
     let plan = sql_to_optimized_ir(sql, vec![]);
-    println!("{}", plan.as_explain().unwrap());
 
     let expected_explain = String::from(
         r#"union all
diff --git a/sbroad-core/src/ir/operator.rs b/sbroad-core/src/ir/operator.rs
index b314bd093..fcc249ad4 100644
--- a/sbroad-core/src/ir/operator.rs
+++ b/sbroad-core/src/ir/operator.rs
@@ -858,6 +858,9 @@ impl Relational {
     ///
     /// # Errors
     /// - relational node is not a scan.
+    ///
+    /// # Panics
+    /// - CTE must have a name.
     pub fn set_scan_name(&mut self, name: Option<SmolStr>) -> Result<(), SbroadError> {
         match self {
             Relational::ScanRelation { ref mut alias, .. }
@@ -865,6 +868,11 @@ impl Relational {
                 *alias = name;
                 Ok(())
             }
+            Relational::ScanCte { ref mut alias, .. } => {
+                let name = name.expect("CTE must have a name");
+                *alias = name;
+                Ok(())
+            }
             _ => Err(SbroadError::Invalid(
                 Entity::Relational,
                 Some("Relational node is not a Scan.".into()),
diff --git a/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection_syntax_nodes.yaml b/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection_syntax_nodes.yaml
index 1dc1e5a2b..956f7a155 100644
--- a/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection_syntax_nodes.yaml
+++ b/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection_syntax_nodes.yaml
@@ -28,11 +28,11 @@ arena:
     right:
       - 0
 #2
-  - data: OpenParenthesis
+  - data: CloseParenthesis
     left: ~
     right: []
 #3
-  - data: CloseParenthesis
+  - data: OpenParenthesis
     left: ~
     right: []
 #4
@@ -40,9 +40,9 @@ arena:
       PlanId: 15
     left: ~
     right:
-      - 2
-      - 1
       - 3
+      - 1
+      - 2
 #5
   - data:
       PlanId: 3
@@ -54,11 +54,11 @@ arena:
     left: ~
     right: []
 #7
-  - data: OpenParenthesis
+  - data: CloseParenthesis
     left: ~
     right: []
 #8
-  - data: CloseParenthesis
+  - data: OpenParenthesis
     left: ~
     right: []
 #9
@@ -66,20 +66,20 @@ arena:
       PlanId: 5
     left: ~
     right:
-      - 7
-      - 6
       - 8
+      - 6
+      - 7
 #10
   - data:
       Parameter: 6
     left: ~
     right: []
 #11
-  - data: OpenParenthesis
+  - data: CloseParenthesis
     left: ~
     right: []
 #12
-  - data: CloseParenthesis
+  - data: OpenParenthesis
     left: ~
     right: []
 #13
@@ -87,9 +87,9 @@ arena:
       PlanId: 7
     left: ~
     right:
-      - 11
-      - 10
       - 12
+      - 10
+      - 11
 #14
   - data:
       Operator: =
@@ -119,15 +119,5 @@ arena:
     right:
       - 1
       - 17
-map:
-  8: 15
-  16: 18
-  4: 6
-  3: 5
-  14: 1
-  13: 0
-  6: 10
-  5: 9
-  7: 13
-  12: 16
-  15: 4
+stack:
+  - 18
-- 
GitLab