diff --git a/benches/engine.rs b/benches/engine.rs
index 527f32121bff22ab68056577f10a62ead16d4298..c612b65b3b3d8790690825fe39a5f4a647e3516b 100644
--- a/benches/engine.rs
+++ b/benches/engine.rs
@@ -6,8 +6,7 @@ use std::collections::HashMap;
 
 use sbroad::errors::QueryPlannerError;
 use sbroad::executor::bucket::Buckets;
-use sbroad::executor::engine::cartridge::backend::sql::ir::get_sql_order;
-use sbroad::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use sbroad::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use sbroad::executor::engine::cartridge::hash::bucket_id_by_tuple;
 use sbroad::executor::engine::{
     normalize_name_from_sql, sharding_keys_from_map, sharding_keys_from_tuple, Configuration,
@@ -415,9 +414,10 @@ impl Coordinator for RouterRuntimeMock {
         buckets: &Buckets,
     ) -> Result<Box<dyn Any>, QueryPlannerError> {
         let result = ProducerResult::new();
-        let mut sp = SyntaxPlan::new(plan, top_id)?;
-        let nodes = get_sql_order(&mut sp)?;
-        plan.syntax_nodes_as_sql(&nodes, buckets)?;
+        let sp = SyntaxPlan::new(plan, top_id)?;
+        let ordered = OrderedSyntaxNodes::try_from(sp)?;
+        let nodes = ordered.to_syntax_data()?;
+        plan.to_sql(&nodes, buckets)?;
 
         Ok(Box::new(result))
     }
diff --git a/benches/parse.rs b/benches/parse.rs
index e4bbbad4df9d83383721312d126a153aeb39bdf0..e4565b377be891d489d59ba43ed6f2eb3a70cd9a 100644
--- a/benches/parse.rs
+++ b/benches/parse.rs
@@ -2,8 +2,7 @@ extern crate sbroad;
 
 use criterion::{criterion_group, criterion_main, Criterion};
 use engine::RouterRuntimeMock;
-use sbroad::executor::engine::cartridge::backend::sql::ir::get_sql_order;
-use sbroad::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use sbroad::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use sbroad::executor::Query;
 use sbroad::ir::value::Value;
 
@@ -239,9 +238,10 @@ fn query1(pattern: &str, params: Vec<Value>, engine: &mut RouterRuntimeMock) {
     let top_id = query.get_exec_plan().get_ir_plan().get_top().unwrap();
     let buckets = query.bucket_discovery(top_id).unwrap();
     let plan = query.get_exec_plan();
-    let mut sp = SyntaxPlan::new(plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    plan.syntax_nodes_as_sql(&nodes, &buckets).unwrap();
+    let sp = SyntaxPlan::new(plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    plan.to_sql(&nodes, &buckets).unwrap();
 }
 
 fn bench_query1(c: &mut Criterion) {
diff --git a/src/executor/engine/cartridge/backend/sql/ir.rs b/src/executor/engine/cartridge/backend/sql/ir.rs
index 4f0bbb0479d0cea180ea63ed382ee9a7718bbc51..7262894e60be069920f742a083acf0166b1cde80 100644
--- a/src/executor/engine/cartridge/backend/sql/ir.rs
+++ b/src/executor/engine/cartridge/backend/sql/ir.rs
@@ -13,7 +13,7 @@ use crate::ir::operator::Relational;
 use crate::ir::value::Value;
 use crate::ir::Node;
 
-use super::tree::{SyntaxData, SyntaxPlan};
+use super::tree::SyntaxData;
 
 #[derive(Debug, PartialEq, Serialize, tlua::Push)]
 pub struct PatternWithParams {
@@ -74,7 +74,7 @@ impl ExecutionPlan {
     /// - plan is invalid and can't be transformed
     #[allow(dead_code)]
     #[allow(clippy::too_many_lines)]
-    pub fn syntax_nodes_as_sql(
+    pub fn to_sql(
         &self,
         nodes: &[&SyntaxData],
         buckets: &Buckets,
@@ -292,48 +292,5 @@ impl ExecutionPlan {
     }
 }
 
-/// Traverse plan sub-tree (pointed by top) in the order
-/// convenient for SQL serialization.
-///
-/// # Panics
-/// - the amount of nodes exceeds `isize::MAX / usize` bytes
-///
-/// # Errors
-/// - top node is invalid
-/// - plan is invalid
-pub fn get_sql_order<'sp>(
-    sp: &'sp mut SyntaxPlan,
-) -> Result<Vec<&'sp SyntaxData>, QueryPlannerError> {
-    // Result with plan node ids.
-    let mut positions: Vec<usize> = Vec::with_capacity(sp.nodes.arena.len());
-    // Stack to keep syntax node data.
-    let mut stack: Vec<usize> = Vec::with_capacity(sp.nodes.arena.len());
-
-    // Make a destructive in-order traversal over the syntax plan
-    // nodes (left and right pointers for any wrapped node become
-    // None or removed). It seems to be the fastest traversal
-    // 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)?;
-        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)?;
-            while let Some(right_id) = sn_next.right.pop() {
-                stack.push(right_id);
-            }
-        }
-    }
-
-    let mut result: Vec<&SyntaxData> = Vec::with_capacity(positions.len());
-    for id in positions {
-        result.push(&sp.nodes.get_syntax_node(id)?.data);
-    }
-
-    Ok(result)
-}
-
 #[cfg(test)]
 mod tests;
diff --git a/src/executor/engine/cartridge/backend/sql/ir/tests.rs b/src/executor/engine/cartridge/backend/sql/ir/tests.rs
index d4fa13b92acda3debd30b154bd4655f371197af6..be5cea5ba98c4adbfecd24034d818a7749e339a8 100644
--- a/src/executor/engine/cartridge/backend/sql/ir/tests.rs
+++ b/src/executor/engine/cartridge/backend/sql/ir/tests.rs
@@ -1,8 +1,7 @@
 use pretty_assertions::assert_eq;
 
 use crate::executor::bucket::Buckets;
-use crate::executor::engine::cartridge::backend::sql::ir::get_sql_order;
-use crate::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use crate::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use crate::executor::engine::mock::RouterConfigurationMock;
 use crate::executor::ir::ExecutionPlan;
 use crate::frontend::sql::ast::AbstractSyntaxTree;
@@ -24,9 +23,10 @@ fn one_table_projection() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -56,9 +56,10 @@ fn one_table_with_asterisk() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -94,9 +95,10 @@ fn union_all() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -129,9 +131,10 @@ fn from_sub_query() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -167,9 +170,10 @@ fn from_sub_query_with_union() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -202,9 +206,10 @@ fn inner_join() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -239,9 +244,10 @@ fn inner_join_with_sq() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -275,9 +281,10 @@ fn selection_with_sq() {
     plan.bind_params(vec![]).unwrap();
     let ex_plan = ExecutionPlan::from(plan);
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
@@ -313,9 +320,10 @@ fn except() {
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    let sql = ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    let sql = ex_plan.to_sql(&nodes, &Buckets::All).unwrap();
 
     assert_eq!(
         PatternWithParams::new(
diff --git a/src/executor/engine/cartridge/backend/sql/tree.rs b/src/executor/engine/cartridge/backend/sql/tree.rs
index 8d20745e65fa3e6475509c412dcad34ebec37f04..937df293f36095a1adb23eba94c63d4d8008341f 100644
--- a/src/executor/engine/cartridge/backend/sql/tree.rs
+++ b/src/executor/engine/cartridge/backend/sql/tree.rs
@@ -1,5 +1,6 @@
 use ahash::RandomState;
 use std::collections::HashMap;
+use std::mem::take;
 use std::rc::Rc;
 
 use serde::{Deserialize, Serialize};
@@ -953,5 +954,65 @@ impl<'p> SyntaxPlan<'p> {
     }
 }
 
+pub struct OrderedSyntaxNodes {
+    arena: Vec<SyntaxNode>,
+    positions: Vec<usize>,
+}
+
+impl OrderedSyntaxNodes {
+    /// Constructs a vector of the syntax node pointers in an order, suitable for building
+    /// an SQL query (in-order traversal).
+    ///
+    /// # Errors
+    /// - internal error (positions point to invalid nodes in the arena)
+    pub fn to_syntax_data(&self) -> Result<Vec<&SyntaxData>, QueryPlannerError> {
+        let mut result: Vec<&SyntaxData> = Vec::with_capacity(self.positions.len());
+        for id in &self.positions {
+            result.push(
+                &self
+                    .arena
+                    .get(*id)
+                    .ok_or_else(|| {
+                        QueryPlannerError::CustomError(format!("Invalid syntax node id: {}", id))
+                    })?
+                    .data,
+            );
+        }
+        Ok(result)
+    }
+}
+
+impl TryFrom<SyntaxPlan<'_>> for OrderedSyntaxNodes {
+    type Error = QueryPlannerError;
+
+    fn try_from(mut sp: SyntaxPlan) -> Result<Self, Self::Error> {
+        // Result with plan node ids.
+        let mut positions: Vec<usize> = Vec::with_capacity(sp.nodes.arena.len());
+        // Stack to keep syntax node data.
+        let mut stack: Vec<usize> = Vec::with_capacity(sp.nodes.arena.len());
+
+        // Make a destructive in-order traversal over the syntax plan
+        // nodes (left and right pointers for any wrapped node become
+        // None or removed). It seems to be the fastest traversal
+        // 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)?;
+            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)?;
+                while let Some(right_id) = sn_next.right.pop() {
+                    stack.push(right_id);
+                }
+            }
+        }
+
+        let arena: Vec<SyntaxNode> = take(&mut sp.nodes.arena);
+        Ok(Self { arena, positions })
+    }
+}
+
 #[cfg(test)]
 mod tests;
diff --git a/src/executor/engine/cartridge/backend/sql/tree/tests.rs b/src/executor/engine/cartridge/backend/sql/tree/tests.rs
index 38c1ba5c14ad757178d1c606cfaff890d6ed5e0c..07776e634c21c909371c0cad4ef25334f22a8fa0 100644
--- a/src/executor/engine/cartridge/backend/sql/tree/tests.rs
+++ b/src/executor/engine/cartridge/backend/sql/tree/tests.rs
@@ -3,8 +3,7 @@ use std::path::Path;
 
 use pretty_assertions::assert_eq;
 
-use crate::executor::engine::cartridge::backend::sql::ir::get_sql_order;
-use crate::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use crate::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use crate::ir::operator::Bool;
 use crate::ir::relation::{Column, ColumnRole, Table, Type};
 use crate::ir::value::Value;
@@ -66,8 +65,9 @@ fn sql_order_selection() {
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
 
     // get nodes in the sql-convenient order
-    let mut sp = SyntaxPlan::new(&exec_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
+    let sp = SyntaxPlan::new(&exec_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
     let mut nodes_iter = nodes.into_iter();
     assert_eq!(Some(&SyntaxData::PlanId(16)), nodes_iter.next()); // projection
     assert_eq!(Some(&SyntaxData::PlanId(14)), nodes_iter.next()); // alias
diff --git a/src/executor/engine/cartridge/router.rs b/src/executor/engine/cartridge/router.rs
index 01f4053f79d3eaaed8701481e5fae11495df1c4e..a21046cb33d47133845a87ecedca200844168c8f 100644
--- a/src/executor/engine/cartridge/router.rs
+++ b/src/executor/engine/cartridge/router.rs
@@ -13,8 +13,8 @@ use tarantool::tuple::Tuple;
 
 use crate::errors::QueryPlannerError;
 use crate::executor::bucket::Buckets;
-use crate::executor::engine::cartridge::backend::sql::ir::{get_sql_order, PatternWithParams};
-use crate::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use crate::executor::engine::cartridge::backend::sql::ir::PatternWithParams;
+use crate::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use crate::executor::engine::cartridge::config::RouterConfiguration;
 use crate::executor::engine::cartridge::hash::bucket_id_by_tuple;
 use crate::executor::engine::{
@@ -168,8 +168,9 @@ impl Coordinator for RouterRuntime {
         top_id: usize,
         buckets: &Buckets,
     ) -> Result<Box<dyn Any>, QueryPlannerError> {
-        let mut sp = SyntaxPlan::new(plan, top_id)?;
-        let nodes = get_sql_order(&mut sp)?;
+        let sp = SyntaxPlan::new(plan, top_id)?;
+        let ordered = OrderedSyntaxNodes::try_from(sp)?;
+        let nodes = ordered.to_syntax_data()?;
         let is_data_modifier = plan.subtree_modifies_data(top_id)?;
 
         let mut rs_query: HashMap<String, PatternWithParams> = HashMap::new();
@@ -197,7 +198,7 @@ impl Coordinator for RouterRuntime {
                     .copied()
                     .collect::<HashSet<u64, RepeatableState>>();
                 let pattern_with_params =
-                    plan.syntax_nodes_as_sql(&nodes, &Buckets::new_filtered(bucket_set))?;
+                    plan.to_sql(&nodes, &Buckets::new_filtered(bucket_set))?;
                 rs_query.insert(rs.to_string(), pattern_with_params);
             }
 
@@ -211,7 +212,7 @@ impl Coordinator for RouterRuntime {
             return self.exec_on_some(&rs_query, is_data_modifier);
         }
 
-        let pattern_with_params = plan.syntax_nodes_as_sql(&nodes, &Buckets::All)?;
+        let pattern_with_params = plan.to_sql(&nodes, &Buckets::All)?;
         self.exec_on_all(&pattern_with_params, is_data_modifier)
     }
 
diff --git a/src/executor/engine/mock.rs b/src/executor/engine/mock.rs
index 84617b0e12d0cb906d98f7403704d8c9aa729b39..2d48379f261aa101c836708d573c50a4e66218fb 100644
--- a/src/executor/engine/mock.rs
+++ b/src/executor/engine/mock.rs
@@ -5,8 +5,7 @@ use std::collections::{HashMap, HashSet};
 use crate::collection;
 use crate::errors::QueryPlannerError;
 use crate::executor::bucket::Buckets;
-use crate::executor::engine::cartridge::backend::sql::ir::get_sql_order;
-use crate::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use crate::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use crate::executor::engine::{
     normalize_name_from_sql, sharding_keys_from_map, sharding_keys_from_tuple, Configuration,
     Coordinator,
@@ -277,18 +276,19 @@ impl Coordinator for RouterRuntimeMock {
         buckets: &Buckets,
     ) -> Result<Box<dyn Any>, QueryPlannerError> {
         let mut result = ProducerResult::new();
-        let mut sp = SyntaxPlan::new(plan, top_id)?;
-        let nodes = get_sql_order(&mut sp)?;
+        let sp = SyntaxPlan::new(plan, top_id)?;
+        let ordered = OrderedSyntaxNodes::try_from(sp)?;
+        let nodes = ordered.to_syntax_data()?;
 
         match buckets {
             Buckets::All => {
-                let sql = plan.syntax_nodes_as_sql(&nodes, buckets)?;
+                let sql = plan.to_sql(&nodes, buckets)?;
                 result.extend(exec_on_all(&String::from(sql).as_str()))?;
             }
             Buckets::Filtered(list) => {
                 for bucket in list {
                     let bucket_set: HashSet<u64, RepeatableState> = collection! { *bucket };
-                    let sql = plan.syntax_nodes_as_sql(&nodes, &Buckets::Filtered(bucket_set))?;
+                    let sql = plan.to_sql(&nodes, &Buckets::Filtered(bucket_set))?;
                     let temp_result = exec_on_some(*bucket, &String::from(sql).as_str());
                     result.extend(temp_result)?;
                 }
diff --git a/src/ir/transformation/helpers.rs b/src/ir/transformation/helpers.rs
index 3c4039b033bb4aa16a477178f864c69c8ef352bb..89f101e9cdbb93079939f127e03b2455a90c15d2 100644
--- a/src/ir/transformation/helpers.rs
+++ b/src/ir/transformation/helpers.rs
@@ -1,8 +1,8 @@
 //! IR test helpers.
 
 use crate::executor::bucket::Buckets;
-use crate::executor::engine::cartridge::backend::sql::ir::{get_sql_order, PatternWithParams};
-use crate::executor::engine::cartridge::backend::sql::tree::SyntaxPlan;
+use crate::executor::engine::cartridge::backend::sql::ir::PatternWithParams;
+use crate::executor::engine::cartridge::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use crate::executor::engine::mock::RouterConfigurationMock;
 use crate::executor::ir::ExecutionPlan;
 use crate::frontend::sql::ast::AbstractSyntaxTree;
@@ -31,7 +31,8 @@ pub fn sql_to_sql(
     f_transform(&mut plan);
     let ex_plan = ExecutionPlan::from(plan);
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let mut sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
-    let nodes = get_sql_order(&mut sp).unwrap();
-    ex_plan.syntax_nodes_as_sql(&nodes, &Buckets::All).unwrap()
+    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
+    let nodes = ordered.to_syntax_data().unwrap();
+    ex_plan.to_sql(&nodes, &Buckets::All).unwrap()
 }