diff --git a/sbroad-benches/benches/parse.rs b/sbroad-benches/benches/parse.rs
index 7bc8e5f9b50b8a43f6316b5e9cf7ccdc162c596d..455221808298a99b03a1ccb047818ba8d75bd2ac 100644
--- a/sbroad-benches/benches/parse.rs
+++ b/sbroad-benches/benches/parse.rs
@@ -1,6 +1,7 @@
 use criterion::{criterion_group, criterion_main, Criterion};
 use sbroad::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use sbroad::executor::Query;
+use sbroad::ir::tree::Snapshot;
 use sbroad::ir::value::Value;
 use sbroad_benches::engine::RouterRuntimeMock;
 
@@ -237,7 +238,7 @@ 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 sp = SyntaxPlan::new(plan, top_id).unwrap();
+    let sp = SyntaxPlan::new(plan, top_id, Snapshot::Oldest).unwrap();
     let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
     let nodes = ordered.to_syntax_data().unwrap();
     plan.to_sql(&nodes, &buckets).unwrap();
diff --git a/sbroad-benches/src/engine.rs b/sbroad-benches/src/engine.rs
index 47e5ff30a87682b14d20b3b41e6d694c82bf7df9..e87a52b35eb1c1e162d5aeb0900ac5f5c8d04256 100644
--- a/sbroad-benches/src/engine.rs
+++ b/sbroad-benches/src/engine.rs
@@ -17,6 +17,7 @@ use sbroad::executor::vtable::VirtualTable;
 use sbroad::frontend::sql::ast::AbstractSyntaxTree;
 use sbroad::ir::function::Function;
 use sbroad::ir::relation::{Column, ColumnRole, Table, Type};
+use sbroad::ir::tree::Snapshot;
 use sbroad::ir::value::Value;
 use sbroad::ir::Plan;
 
@@ -431,7 +432,7 @@ impl Coordinator for RouterRuntimeMock {
         buckets: &Buckets,
     ) -> Result<Box<dyn Any>, QueryPlannerError> {
         let result = ProducerResult::new();
-        let sp = SyntaxPlan::new(plan, top_id)?;
+        let sp = SyntaxPlan::new(plan, top_id, Snapshot::Oldest)?;
         let ordered = OrderedSyntaxNodes::try_from(sp)?;
         let nodes = ordered.to_syntax_data()?;
         plan.to_sql(&nodes, buckets)?;
diff --git a/sbroad-cartridge/src/cartridge/router.rs b/sbroad-cartridge/src/cartridge/router.rs
index fd7ed9a2c0afe136eded9a96e62f10b5dc60d3cf..cdad68b649e297f142d638c6efd839ae9109ec40 100644
--- a/sbroad-cartridge/src/cartridge/router.rs
+++ b/sbroad-cartridge/src/cartridge/router.rs
@@ -30,6 +30,7 @@ use sbroad::executor::result::ProducerResult;
 use sbroad::executor::vtable::VirtualTable;
 use sbroad::frontend::sql::ast::AbstractSyntaxTree;
 use sbroad::ir::helpers::RepeatableState;
+use sbroad::ir::tree::Snapshot;
 use sbroad::ir::value::Value;
 use sbroad::ir::Plan;
 use sbroad::otm::child_span;
@@ -185,7 +186,7 @@ impl Coordinator for RouterRuntime {
         top_id: usize,
         buckets: &Buckets,
     ) -> Result<Box<dyn Any>, QueryPlannerError> {
-        let sp = SyntaxPlan::new(plan, top_id)?;
+        let sp = SyntaxPlan::new(plan, top_id, Snapshot::Oldest)?;
         let ordered = OrderedSyntaxNodes::try_from(sp)?;
         let nodes = ordered.to_syntax_data()?;
         let is_data_modifier = plan.subtree_modifies_data(top_id)?;
diff --git a/sbroad-cartridge/test_app/test/data/test_data.lua b/sbroad-cartridge/test_app/test/data/test_data.lua
index 4770dfa22c3ddb56c68b1db114ce380296778420..f36b66d55cbe913d23af09d9687a35ecd57814bd 100644
--- a/sbroad-cartridge/test_app/test/data/test_data.lua
+++ b/sbroad-cartridge/test_app/test/data/test_data.lua
@@ -1,5 +1,15 @@
 local vsa_proxy_records = {
-    { 6659253, -20191, 0, "111", box.NULL, "{\"inn\":1234567890\"\",\"name\":\"КАПИБАРА ТЮЛЕНЬ ВОМБАТОВИЧ\"}", "", box.NULL, box.NULL },
+    {
+        6659253,
+        -20191,
+        0,
+        "111",
+        box.NULL,
+        "{\"inn\":1234567890\"\",\"name\":\"КАПИБАРА ТЮЛЕНЬ ВОМБАТОВИЧ\"}",
+        "",
+        box.NULL,
+        box.NULL
+    },
 }
 
 return {
diff --git a/sbroad-cartridge/test_app/test/integration/large_query_test.lua b/sbroad-cartridge/test_app/test/integration/large_query_test.lua
index 3dfaa876746d5bdbce66c411dffa40ef8b0a9088..bbf9e530a8006d34d124f5349bacf69cd049c258 100644
--- a/sbroad-cartridge/test_app/test/integration/large_query_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/large_query_test.lua
@@ -116,8 +116,12 @@ g.before_all(
         local _, err = api:call(
           "sbroad.execute",
           {
-            [[INSERT INTO "VSA_PROXY"
-               ("fid","date_start","date_end","common_id","exclude_id", "common_text", "common_detail", "typology_type", "typology_id")
+            [[INSERT INTO "VSA_PROXY" (
+              "fid", "date_start", "date_end",
+              "common_id", "exclude_id",
+              "common_text", "common_detail",
+              "typology_type", "typology_id"
+             )
              VALUES (?,?,?,?,?,?,?,?,?)]],
             rec
           }
diff --git a/sbroad-core/src/backend/sql/ir/tests.rs b/sbroad-core/src/backend/sql/ir/tests.rs
index 1c34f1f83e8baad40a94709562def36ae5df910f..27146258d47cd0818d0bf9f563f2532fa9330f18 100644
--- a/sbroad-core/src/backend/sql/ir/tests.rs
+++ b/sbroad-core/src/backend/sql/ir/tests.rs
@@ -6,337 +6,45 @@ use crate::executor::engine::mock::RouterConfigurationMock;
 use crate::executor::ir::ExecutionPlan;
 use crate::frontend::sql::ast::AbstractSyntaxTree;
 use crate::frontend::Ast;
-use crate::ir::value::Value;
+use crate::ir::tree::Snapshot;
 
 use super::*;
 
-#[test]
-fn one_table_projection() {
-    let query = r#"SELECT "identification_number", "product_code"
-    FROM "hash_testing"
-    WHERE "identification_number" = 1"#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {}",
-                r#"SELECT "hash_testing"."identification_number","#,
-                r#""hash_testing"."product_code""#,
-                r#"FROM "hash_testing""#,
-                r#"WHERE ("hash_testing"."identification_number") = (?)"#,
-            ),
-            vec![Value::from(1_u64)]
-        ),
-        sql
-    );
-}
-
-#[test]
-fn one_table_with_asterisk() {
-    let query = r#"SELECT *
-    FROM "hash_testing"
-    WHERE "identification_number" = 1"#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {} {}",
-                r#"SELECT "hash_testing"."identification_number","#,
-                r#""hash_testing"."product_code","#,
-                r#""hash_testing"."product_units", "hash_testing"."sys_op""#,
-                r#"FROM "hash_testing""#,
-                r#"WHERE ("hash_testing"."identification_number") = (?)"#
-            ),
-            vec![Value::from(1_u64)]
-        ),
-        sql
-    );
-}
-
-#[test]
-fn union_all() {
-    let query = r#"SELECT "product_code"
-    FROM "hash_testing"
-    WHERE "identification_number" = 1
-    UNION ALL
-    SELECT "product_code"
-    FROM "hash_testing_hist"
-    WHERE "product_code" = 'a' 
-    "#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {} {}",
-                r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
-                r#"WHERE ("hash_testing"."identification_number") = (?)"#,
-                r#"UNION ALL"#,
-                r#"SELECT "hash_testing_hist"."product_code" FROM "hash_testing_hist""#,
-                r#"WHERE ("hash_testing_hist"."product_code") = (?)"#
-            ),
-            vec![Value::from(1_u64), Value::from("a")],
-        ),
-        sql
-    );
-}
-
-#[test]
-fn from_sub_query() {
-    let query = r#"SELECT "product_code"
-    FROM (SELECT "product_code"
-    FROM "hash_testing"
-    WHERE "identification_number" = 1) as t1
-    WHERE "product_code" = 'a'"#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {}",
-                r#"SELECT "T1"."product_code" FROM"#,
-                r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#,
-                r#"WHERE ("hash_testing"."identification_number") = (?)) as "T1""#,
-                r#"WHERE ("T1"."product_code") = (?)"#
-            ),
-            vec![Value::from(1_u64), Value::from("a")],
-        ),
-        sql
-    );
-}
-
-#[test]
-fn from_sub_query_with_union() {
-    let query = r#"SELECT "product_code"
-  FROM (SELECT "product_code"
-    FROM "hash_testing"
-    WHERE "identification_number" = 1
-    UNION ALL
-    SELECT "product_code"
-    FROM "hash_testing_hist"
-    WHERE "product_code" = 'a') as "t1"
-  WHERE "product_code" = 'a'"#;
-
+fn check_sql_with_snapshot(query: &str, expected: PatternWithParams, snapshot: Snapshot) {
     let metadata = &RouterConfigurationMock::new();
     let ast = AbstractSyntaxTree::new(query).unwrap();
     let mut plan = ast.resolve_metadata(metadata).unwrap();
     plan.bind_params(vec![]).unwrap();
+    plan.replace_in_operator().unwrap();
+    plan.split_columns().unwrap();
+    plan.set_dnf().unwrap();
+    plan.derive_equalities().unwrap();
+    plan.merge_tuples().unwrap();
     let ex_plan = ExecutionPlan::from(plan);
 
     let top_id = ex_plan.get_ir_plan().get_top().unwrap();
-    let sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id, snapshot).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(
-            format!(
-                "{} {} {} {} {} {} {}",
-                r#"SELECT "t1"."product_code" FROM"#,
-                r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#,
-                r#"WHERE ("hash_testing"."identification_number") = (?)"#,
-                r#"UNION ALL"#,
-                r#"SELECT "hash_testing_hist"."product_code" FROM "hash_testing_hist""#,
-                r#"WHERE ("hash_testing_hist"."product_code") = (?)) as "t1""#,
-                r#"WHERE ("t1"."product_code") = (?)"#,
-            ),
-            vec![Value::from(1_u64), Value::from("a"), Value::from("a")],
-        ),
-        sql
-    );
+    assert_eq!(expected, sql,);
 }
 
-#[test]
-fn inner_join() {
-    let query = r#"SELECT "product_code" FROM "hash_testing" join "history"
-    on "hash_testing"."identification_number" = "history"."id"
-    WHERE "product_code" = 'a'"#;
+#[cfg(test)]
+mod except;
 
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
+#[cfg(test)]
+mod projection;
 
-    let top_id = ex_plan.get_ir_plan().get_top().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();
+#[cfg(test)]
+mod inner_join;
 
-    assert_eq!(
-        PatternWithParams::new(
-            format!(
-                "{} {} {} {} {} {} {} {}",
-                r#"SELECT "hash_testing"."product_code""#,
-                r#"FROM (SELECT "hash_testing"."identification_number","#,
-                r#""hash_testing"."product_code","#,
-                r#""hash_testing"."product_units","#,
-                r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#,
-                r#"INNER JOIN (SELECT "history"."id" FROM "history") as "history""#,
-                r#"ON ("hash_testing"."identification_number") = ("history"."id")"#,
-                r#"WHERE ("hash_testing"."product_code") = (?)"#,
-            ),
-            vec![Value::from("a")],
-        ),
-        sql
-    );
-}
+#[cfg(test)]
+mod selection;
 
-#[test]
-fn inner_join_with_sq() {
-    let query = r#"SELECT "product_code" FROM "hash_testing" join
-    (SELECT * FROM "history" WHERE "id" = 1) as "t"
-    on "hash_testing"."identification_number" = "t"."id"
-    WHERE "product_code" = 'a'"#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {} {} {} {} {} {}",
-                r#"SELECT "hash_testing"."product_code" FROM (SELECT"#,
-                r#""hash_testing"."identification_number","#,
-                r#""hash_testing"."product_code","#,
-                r#""hash_testing"."product_units","#,
-                r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#,
-                r#"INNER JOIN"#,
-                r#"(SELECT "history"."id" FROM "history" WHERE ("history"."id") = (?)) as "t""#,
-                r#"ON ("hash_testing"."identification_number") = ("t"."id")"#,
-                r#"WHERE ("hash_testing"."product_code") = (?)"#,
-            ),
-            vec![Value::from(1_u64), Value::from("a")],
-        ),
-        sql
-    );
-}
+#[cfg(test)]
+mod sub_query;
 
-#[test]
-fn selection_with_sq() {
-    let query = r#"SELECT "product_code" FROM "hash_testing"
-    WHERE "identification_number" in
-    (SELECT "identification_number" FROM "hash_testing_hist" WHERE "product_code" = 'b') and "product_code" < 'a'"#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {} {}",
-                r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
-                r#"WHERE ("hash_testing"."identification_number") in"#,
-                r#"(SELECT "hash_testing_hist"."identification_number" FROM "hash_testing_hist""#,
-                r#"WHERE ("hash_testing_hist"."product_code") = (?))"#,
-                r#"and ("hash_testing"."product_code") < (?)"#,
-            ),
-            vec![Value::from("b"), Value::from("a")],
-        ),
-        sql
-    );
-}
-
-#[test]
-fn except() {
-    let query = r#"SELECT "id"
-    FROM "test_space"
-    WHERE "sysFrom" = 1
-    EXCEPT DISTINCT
-    SELECT "id"
-    FROM "test_space"
-    WHERE "FIRST_NAME" = 'a' 
-    "#;
-
-    let metadata = &RouterConfigurationMock::new();
-    let ast = AbstractSyntaxTree::new(query).unwrap();
-    let mut plan = ast.resolve_metadata(metadata).unwrap();
-    plan.bind_params(vec![]).unwrap();
-    let ex_plan = ExecutionPlan::from(plan);
-
-    let top_id = ex_plan.get_ir_plan().get_top().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(
-            format!(
-                "{} {} {} {} {}",
-                r#"SELECT "test_space"."id" FROM "test_space""#,
-                r#"WHERE ("test_space"."sysFrom") = (?)"#,
-                r#"EXCEPT"#,
-                r#"SELECT "test_space"."id" FROM "test_space""#,
-                r#"WHERE ("test_space"."FIRST_NAME") = (?)"#
-            ),
-            vec![Value::from(1_u64), Value::from("a")],
-        ),
-        sql
-    );
-}
+#[cfg(test)]
+mod union_all;
diff --git a/sbroad-core/src/backend/sql/ir/tests/except.rs b/sbroad-core/src/backend/sql/ir/tests/except.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b12eb3069619a6efcd267c2fe7a84dbc56e49561
--- /dev/null
+++ b/sbroad-core/src/backend/sql/ir/tests/except.rs
@@ -0,0 +1,51 @@
+use super::*;
+use crate::ir::tree::Snapshot;
+use crate::ir::value::Value;
+
+#[test]
+fn except1_latest() {
+    let query = r#"SELECT "id"
+        FROM "test_space"
+        WHERE "sysFrom" = 1
+        EXCEPT DISTINCT
+        SELECT "id"
+        FROM "test_space"
+        WHERE "FIRST_NAME" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "test_space"."id" FROM "test_space""#,
+            r#"WHERE ("test_space"."sysFrom") = (?)"#,
+            r#"EXCEPT"#,
+            r#"SELECT "test_space"."id" FROM "test_space""#,
+            r#"WHERE ("test_space"."FIRST_NAME") = (?)"#
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn except1_oldest() {
+    let query = r#"SELECT "id"
+        FROM "test_space"
+        WHERE "sysFrom" = 1
+        EXCEPT DISTINCT
+        SELECT "id"
+        FROM "test_space"
+        WHERE "FIRST_NAME" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "test_space"."id" FROM "test_space""#,
+            r#"WHERE ("test_space"."sysFrom") = (?)"#,
+            r#"EXCEPT"#,
+            r#"SELECT "test_space"."id" FROM "test_space""#,
+            r#"WHERE ("test_space"."FIRST_NAME") = (?)"#
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
diff --git a/sbroad-core/src/backend/sql/ir/tests/inner_join.rs b/sbroad-core/src/backend/sql/ir/tests/inner_join.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2c714a7e85acae8e19b5c4c0fbe64313273a0e9d
--- /dev/null
+++ b/sbroad-core/src/backend/sql/ir/tests/inner_join.rs
@@ -0,0 +1,99 @@
+use super::*;
+use crate::ir::tree::Snapshot;
+use crate::ir::value::Value;
+
+#[test]
+fn inner_join1_latest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing" join "history"
+        on "hash_testing"."identification_number" = "history"."id"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code""#,
+            r#"FROM (SELECT "hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code","#,
+            r#""hash_testing"."product_units","#,
+            r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#,
+            r#"INNER JOIN (SELECT "history"."id" FROM "history") as "history""#,
+            r#"ON ("hash_testing"."identification_number") = ("history"."id")"#,
+            r#"WHERE ("hash_testing"."product_code") = (?)"#,
+        ),
+        vec![Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn inner_join1_oldest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing" join "history"
+        on "hash_testing"."identification_number" = "history"."id"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code""#,
+            r#"FROM (SELECT "hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code","#,
+            r#""hash_testing"."product_units","#,
+            r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#,
+            r#"INNER JOIN (SELECT "history"."id" FROM "history") as "history""#,
+            r#"ON ("hash_testing"."identification_number") = ("history"."id")"#,
+            r#"WHERE ("hash_testing"."product_code") = (?)"#,
+        ),
+        vec![Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
+
+#[test]
+fn inner_join2_latest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing" join
+        (SELECT * FROM "history" WHERE "id" = 1) as "t"
+        on "hash_testing"."identification_number" = "t"."id"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM (SELECT"#,
+            r#""hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code","#,
+            r#""hash_testing"."product_units","#,
+            r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#,
+            r#"INNER JOIN"#,
+            r#"(SELECT "history"."id" FROM "history" WHERE ("history"."id") = (?)) as "t""#,
+            r#"ON ("hash_testing"."identification_number") = ("t"."id")"#,
+            r#"WHERE ("hash_testing"."product_code") = (?)"#,
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn inner_join2_oldest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing" join
+        (SELECT * FROM "history" WHERE "id" = 1) as "t"
+        on "hash_testing"."identification_number" = "t"."id"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM (SELECT"#,
+            r#""hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code","#,
+            r#""hash_testing"."product_units","#,
+            r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#,
+            r#"INNER JOIN"#,
+            r#"(SELECT "history"."id" FROM "history" WHERE ("history"."id") = (?)) as "t""#,
+            r#"ON ("hash_testing"."identification_number") = ("t"."id")"#,
+            r#"WHERE ("hash_testing"."product_code") = (?)"#,
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
diff --git a/sbroad-core/src/backend/sql/ir/tests/projection.rs b/sbroad-core/src/backend/sql/ir/tests/projection.rs
new file mode 100644
index 0000000000000000000000000000000000000000..57c1b248b20dc1591ac9a8193808891bab02e71a
--- /dev/null
+++ b/sbroad-core/src/backend/sql/ir/tests/projection.rs
@@ -0,0 +1,79 @@
+use super::*;
+use crate::ir::tree::Snapshot;
+use crate::ir::value::Value;
+
+#[test]
+fn projection1_latest() {
+    let query = r#"SELECT "identification_number", "product_code"
+        FROM "hash_testing"
+        WHERE "identification_number" = 1"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {}",
+            r#"SELECT "hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code""#,
+            r#"FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#,
+        ),
+        vec![Value::from(1_u64)],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn projection1_oldest() {
+    let query = r#"SELECT "identification_number", "product_code"
+        FROM "hash_testing"
+        WHERE "identification_number" = 1"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {}",
+            r#"SELECT "hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code""#,
+            r#"FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#,
+        ),
+        vec![Value::from(1_u64)],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
+
+#[test]
+fn projection2_latest() {
+    let query = r#"SELECT *
+        FROM "hash_testing"
+        WHERE "identification_number" = 1"#;
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code","#,
+            r#""hash_testing"."product_units", "hash_testing"."sys_op""#,
+            r#"FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#
+        ),
+        vec![Value::from(1_u64)],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn projection2_oldest() {
+    let query = r#"SELECT *
+        FROM "hash_testing"
+        WHERE "identification_number" = 1"#;
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "hash_testing"."identification_number","#,
+            r#""hash_testing"."product_code","#,
+            r#""hash_testing"."product_units", "hash_testing"."sys_op""#,
+            r#"FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#
+        ),
+        vec![Value::from(1_u64)],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
diff --git a/sbroad-core/src/backend/sql/ir/tests/selection.rs b/sbroad-core/src/backend/sql/ir/tests/selection.rs
new file mode 100644
index 0000000000000000000000000000000000000000..0759275feeb8a00dfdd0f35b4d7baa400f64f331
--- /dev/null
+++ b/sbroad-core/src/backend/sql/ir/tests/selection.rs
@@ -0,0 +1,600 @@
+use super::*;
+use crate::ir::tree::Snapshot;
+use crate::ir::value::Value;
+
+#[test]
+fn selection1_latest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing"
+        WHERE "identification_number" in
+        (SELECT "identification_number" FROM "hash_testing_hist" WHERE "product_code" = 'b') and "product_code" < 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."product_code") < (?)"#,
+            r#"and ("hash_testing"."identification_number") in"#,
+            r#"(SELECT "hash_testing_hist"."identification_number" FROM "hash_testing_hist""#,
+            r#"WHERE ("hash_testing_hist"."product_code") = (?))"#,
+        ),
+        vec![Value::from("a"), Value::from("b")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn selection1_oldest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing"
+        WHERE "identification_number" in
+        (SELECT "identification_number" FROM "hash_testing_hist" WHERE "product_code" = 'b') and "product_code" < 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") in"#,
+            r#"(SELECT "hash_testing_hist"."identification_number" FROM "hash_testing_hist""#,
+            r#"WHERE ("hash_testing_hist"."product_code") = (?))"#,
+            r#"and ("hash_testing"."product_code") < (?)"#,
+        ),
+        vec![Value::from("b"), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
+
+#[test]
+fn selection2_latest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing"
+        WHERE "identification_number" IN (6659253, -21, 5933116, 8257405, 3676468, 6580234, 9557717)
+        AND "product_code" IN (6659253, -21, 5933116, 8257405, 3676468, 6580234, 9557717)
+        AND "identification_number" < "product_code"
+        AND ("product_units" <> "sys_op" OR "product_units" IS NULL)"#;
+
+    let expected = PatternWithParams::new(
+            [
+                r#"SELECT "hash_testing"."product_code" FROM "hash_testing" WHERE (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op")"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") <> ("hash_testing"."sys_op"))"#,
+                r#"or ("hash_testing"."identification_number", "hash_testing"."identification_number", "hash_testing"."product_code") = ("hash_testing"."product_code", ?, ?)"#,
+                r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+                r#"and ("hash_testing"."product_units") is null)"#,
+            ].join(" "),
+        vec![
+            Value::from(6659253_u64),
+            Value::from(6659253_u64),
+            Value::from(6659253_u64),
+            Value::from(6659253_u64),
+            Value::from(6659253_u64),
+            Value::from(-21_i64),
+            Value::from(6659253_u64),
+            Value::from(-21_i64),
+            Value::from(6659253_u64),
+            Value::from(5933116_u64),
+            Value::from(6659253_u64),
+            Value::from(5933116_u64),
+            Value::from(6659253_u64),
+            Value::from(8257405_u64),
+            Value::from(6659253_u64),
+            Value::from(8257405_u64),
+            Value::from(6659253_u64),
+            Value::from(3676468_u64),
+            Value::from(6659253_u64),
+            Value::from(3676468_u64),
+            Value::from(6659253_u64),
+            Value::from(6580234_u64),
+            Value::from(6659253_u64),
+            Value::from(6580234_u64),
+            Value::from(6659253_u64),
+            Value::from(9557717_u64),
+            Value::from(6659253_u64),
+            Value::from(9557717_u64),
+            Value::from(-21_i64),
+            Value::from(6659253_u64),
+            Value::from(-21_i64),
+            Value::from(6659253_u64),
+            Value::from(-21_i64),
+            Value::from(-21_i64),
+            Value::from(-21_i64),
+            Value::from(-21_i64),
+            Value::from(-21_i64),
+            Value::from(5933116_u64),
+            Value::from(-21_i64),
+            Value::from(5933116_u64),
+            Value::from(-21_i64),
+            Value::from(8257405_u64),
+            Value::from(-21_i64),
+            Value::from(8257405_u64),
+            Value::from(-21_i64),
+            Value::from(3676468_u64),
+            Value::from(-21_i64),
+            Value::from(3676468_u64),
+            Value::from(-21_i64),
+            Value::from(6580234_u64),
+            Value::from(-21_i64),
+            Value::from(6580234_u64),
+            Value::from(-21_i64),
+            Value::from(9557717_u64),
+            Value::from(-21_i64),
+            Value::from(9557717_u64),
+            Value::from(5933116_u64),
+            Value::from(6659253_u64),
+            Value::from(5933116_u64),
+            Value::from(6659253_u64),
+            Value::from(5933116_u64),
+            Value::from(-21_i64),
+            Value::from(5933116_u64),
+            Value::from(-21_i64),
+            Value::from(5933116_u64),
+            Value::from(5933116_u64),
+            Value::from(5933116_u64),
+            Value::from(5933116_u64),
+            Value::from(5933116_u64),
+            Value::from(8257405_u64),
+            Value::from(5933116_u64),
+            Value::from(8257405_u64),
+            Value::from(5933116_u64),
+            Value::from(3676468_u64),
+            Value::from(5933116_u64),
+            Value::from(3676468_u64),
+            Value::from(5933116_u64),
+            Value::from(6580234_u64),
+            Value::from(5933116_u64),
+            Value::from(6580234_u64),
+            Value::from(5933116_u64),
+            Value::from(9557717_u64),
+            Value::from(5933116_u64),
+            Value::from(9557717_u64),
+            Value::from(8257405_u64),
+            Value::from(6659253_u64),
+            Value::from(8257405_u64),
+            Value::from(6659253_u64),
+            Value::from(8257405_u64),
+            Value::from(-21_i64),
+            Value::from(8257405_u64),
+            Value::from(-21_i64),
+            Value::from(8257405_u64),
+            Value::from(5933116_u64),
+            Value::from(8257405_u64),
+            Value::from(5933116_u64),
+            Value::from(8257405_u64),
+            Value::from(8257405_u64),
+            Value::from(8257405_u64),
+            Value::from(8257405_u64),
+            Value::from(8257405_u64),
+            Value::from(3676468_u64),
+            Value::from(8257405_u64),
+            Value::from(3676468_u64),
+            Value::from(8257405_u64),
+            Value::from(6580234_u64),
+            Value::from(8257405_u64),
+            Value::from(6580234_u64),
+            Value::from(8257405_u64),
+            Value::from(9557717_u64),
+            Value::from(8257405_u64),
+            Value::from(9557717_u64),
+            Value::from(3676468_u64),
+            Value::from(6659253_u64),
+            Value::from(3676468_u64),
+            Value::from(6659253_u64),
+            Value::from(3676468_u64),
+            Value::from(-21_i64),
+            Value::from(3676468_u64),
+            Value::from(-21_i64),
+            Value::from(3676468_u64),
+            Value::from(5933116_u64),
+            Value::from(3676468_u64),
+            Value::from(5933116_u64),
+            Value::from(3676468_u64),
+            Value::from(8257405_u64),
+            Value::from(3676468_u64),
+            Value::from(8257405_u64),
+            Value::from(3676468_u64),
+            Value::from(3676468_u64),
+            Value::from(3676468_u64),
+            Value::from(3676468_u64),
+            Value::from(3676468_u64),
+            Value::from(6580234_u64),
+            Value::from(3676468_u64),
+            Value::from(6580234_u64),
+            Value::from(3676468_u64),
+            Value::from(9557717_u64),
+            Value::from(3676468_u64),
+            Value::from(9557717_u64),
+            Value::from(6580234_u64),
+            Value::from(6659253_u64),
+            Value::from(6580234_u64),
+            Value::from(6659253_u64),
+            Value::from(6580234_u64),
+            Value::from(-21_i64),
+            Value::from(6580234_u64),
+            Value::from(-21_i64),
+            Value::from(6580234_u64),
+            Value::from(5933116_u64),
+            Value::from(6580234_u64),
+            Value::from(5933116_u64),
+            Value::from(6580234_u64),
+            Value::from(8257405_u64),
+            Value::from(6580234_u64),
+            Value::from(8257405_u64),
+            Value::from(6580234_u64),
+            Value::from(3676468_u64),
+            Value::from(6580234_u64),
+            Value::from(3676468_u64),
+            Value::from(6580234_u64),
+            Value::from(6580234_u64),
+            Value::from(6580234_u64),
+            Value::from(6580234_u64),
+            Value::from(6580234_u64),
+            Value::from(9557717_u64),
+            Value::from(6580234_u64),
+            Value::from(9557717_u64),
+            Value::from(9557717_u64),
+            Value::from(6659253_u64),
+            Value::from(9557717_u64),
+            Value::from(6659253_u64),
+            Value::from(9557717_u64),
+            Value::from(-21_i64),
+            Value::from(9557717_u64),
+            Value::from(-21_i64),
+            Value::from(9557717_u64),
+            Value::from(5933116_u64),
+            Value::from(9557717_u64),
+            Value::from(5933116_u64),
+            Value::from(9557717_u64),
+            Value::from(8257405_u64),
+            Value::from(9557717_u64),
+            Value::from(8257405_u64),
+            Value::from(9557717_u64),
+            Value::from(3676468_u64),
+            Value::from(9557717_u64),
+            Value::from(3676468_u64),
+            Value::from(9557717_u64),
+            Value::from(6580234_u64),
+            Value::from(9557717_u64),
+            Value::from(6580234_u64),
+            Value::from(9557717_u64),
+            Value::from(9557717_u64),
+            Value::from(9557717_u64),
+            Value::from(9557717_u64),
+        ],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn selection2_oldest() {
+    let query = r#"SELECT "product_code" FROM "hash_testing"
+        WHERE "identification_number" IN (6659253, -21, 5933116, 8257405, 3676468, 6580234, 9557717)
+        AND "product_code" IN (6659253, -21, 5933116, 8257405, 3676468, 6580234, 9557717)
+        AND "identification_number" < "product_code"
+        AND ("product_units" <> "sys_op" OR "product_units" IS NULL)"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ((((((("hash_testing"."identification_number") = (?)"#,
+            r#"or ("hash_testing"."identification_number") = (?))"#,
+            r#"or ("hash_testing"."identification_number") = (?))"#,
+            r#"or ("hash_testing"."identification_number") = (?))"#,
+            r#"or ("hash_testing"."identification_number") = (?))"#,
+            r#"or ("hash_testing"."identification_number") = (?))"#,
+            r#"or ("hash_testing"."identification_number") = (?))"#,
+            r#"and ((((((("hash_testing"."product_code") = (?)"#,
+            r#"or ("hash_testing"."product_code") = (?))"#,
+            r#"or ("hash_testing"."product_code") = (?))"#,
+            r#"or ("hash_testing"."product_code") = (?))"#,
+            r#"or ("hash_testing"."product_code") = (?))"#,
+            r#"or ("hash_testing"."product_code") = (?))"#,
+            r#"or ("hash_testing"."product_code") = (?))"#,
+            r#"and ("hash_testing"."identification_number") < ("hash_testing"."product_code")"#,
+            r#"and (("hash_testing"."product_units") <> ("hash_testing"."sys_op")"#,
+            r#"or ("hash_testing"."product_units") is null)"#,
+        ),
+        vec![
+            Value::from(6659253_u64),
+            Value::from(-21_i64),
+            Value::from(5933116_u64),
+            Value::from(8257405_u64),
+            Value::from(3676468_u64),
+            Value::from(6580234_u64),
+            Value::from(9557717_u64),
+            Value::from(6659253_u64),
+            Value::from(-21_i64),
+            Value::from(5933116_u64),
+            Value::from(8257405_u64),
+            Value::from(3676468_u64),
+            Value::from(6580234_u64),
+            Value::from(9557717_u64),
+        ],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
diff --git a/sbroad-core/src/backend/sql/ir/tests/sub_query.rs b/sbroad-core/src/backend/sql/ir/tests/sub_query.rs
new file mode 100644
index 0000000000000000000000000000000000000000..3b35a158fb097d2b501905236ccd44054a42d8da
--- /dev/null
+++ b/sbroad-core/src/backend/sql/ir/tests/sub_query.rs
@@ -0,0 +1,101 @@
+use super::*;
+use crate::ir::tree::Snapshot;
+use crate::ir::value::Value;
+
+#[test]
+fn sub_query1_latest() {
+    let query = r#"SELECT "product_code"
+        FROM (SELECT "product_code"
+        FROM "hash_testing"
+        WHERE "identification_number" = 1) as t1
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {}",
+            r#"SELECT "T1"."product_code" FROM"#,
+            r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)) as "T1""#,
+            r#"WHERE ("T1"."product_code") = (?)"#
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn sub_query1_oldest() {
+    let query = r#"SELECT "product_code"
+        FROM (SELECT "product_code"
+        FROM "hash_testing"
+        WHERE "identification_number" = 1) as t1
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {}",
+            r#"SELECT "T1"."product_code" FROM"#,
+            r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)) as "T1""#,
+            r#"WHERE ("T1"."product_code") = (?)"#
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
+
+#[test]
+fn sub_query2_latest() {
+    let query = r#"SELECT "product_code"
+        FROM (SELECT "product_code"
+            FROM "hash_testing"
+            WHERE "identification_number" = 1
+            UNION ALL
+            SELECT "product_code"
+            FROM "hash_testing_hist"
+            WHERE "product_code" = 'a') as "t1"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {}",
+            r#"SELECT "t1"."product_code" FROM"#,
+            r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#,
+            r#"UNION ALL"#,
+            r#"SELECT "hash_testing_hist"."product_code" FROM "hash_testing_hist""#,
+            r#"WHERE ("hash_testing_hist"."product_code") = (?)) as "t1""#,
+            r#"WHERE ("t1"."product_code") = (?)"#,
+        ),
+        vec![Value::from(1_u64), Value::from("a"), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn sub_query2_oldest() {
+    let query = r#"SELECT "product_code"
+        FROM (SELECT "product_code"
+            FROM "hash_testing"
+            WHERE "identification_number" = 1
+            UNION ALL
+            SELECT "product_code"
+            FROM "hash_testing_hist"
+            WHERE "product_code" = 'a') as "t1"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {} {} {}",
+            r#"SELECT "t1"."product_code" FROM"#,
+            r#"(SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#,
+            r#"UNION ALL"#,
+            r#"SELECT "hash_testing_hist"."product_code" FROM "hash_testing_hist""#,
+            r#"WHERE ("hash_testing_hist"."product_code") = (?)) as "t1""#,
+            r#"WHERE ("t1"."product_code") = (?)"#,
+        ),
+        vec![Value::from(1_u64), Value::from("a"), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
diff --git a/sbroad-core/src/backend/sql/ir/tests/union_all.rs b/sbroad-core/src/backend/sql/ir/tests/union_all.rs
new file mode 100644
index 0000000000000000000000000000000000000000..008c27e87671a57031e6450d03b006ba57942cd9
--- /dev/null
+++ b/sbroad-core/src/backend/sql/ir/tests/union_all.rs
@@ -0,0 +1,51 @@
+use super::*;
+use crate::ir::tree::Snapshot;
+use crate::ir::value::Value;
+
+#[test]
+fn union_all1_latest() {
+    let query = r#"SELECT "product_code"
+        FROM "hash_testing"
+        WHERE "identification_number" = 1
+        UNION ALL
+        SELECT "product_code"
+        FROM "hash_testing_hist"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#,
+            r#"UNION ALL"#,
+            r#"SELECT "hash_testing_hist"."product_code" FROM "hash_testing_hist""#,
+            r#"WHERE ("hash_testing_hist"."product_code") = (?)"#
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Latest);
+}
+
+#[test]
+fn union_all1_oldest() {
+    let query = r#"SELECT "product_code"
+        FROM "hash_testing"
+        WHERE "identification_number" = 1
+        UNION ALL
+        SELECT "product_code"
+        FROM "hash_testing_hist"
+        WHERE "product_code" = 'a'"#;
+
+    let expected = PatternWithParams::new(
+        format!(
+            "{} {} {} {} {}",
+            r#"SELECT "hash_testing"."product_code" FROM "hash_testing""#,
+            r#"WHERE ("hash_testing"."identification_number") = (?)"#,
+            r#"UNION ALL"#,
+            r#"SELECT "hash_testing_hist"."product_code" FROM "hash_testing_hist""#,
+            r#"WHERE ("hash_testing_hist"."product_code") = (?)"#
+        ),
+        vec![Value::from(1_u64), Value::from("a")],
+    );
+    check_sql_with_snapshot(query, expected, Snapshot::Oldest);
+}
diff --git a/sbroad-core/src/backend/sql/tree.rs b/sbroad-core/src/backend/sql/tree.rs
index a5b20f9aa6ca4824605ed7311fa5fb0173800056..8c1649d23d0b25c83d45dff5b4e21b7adef8bb31 100644
--- a/sbroad-core/src/backend/sql/tree.rs
+++ b/sbroad-core/src/backend/sql/tree.rs
@@ -11,6 +11,7 @@ use crate::executor::ir::ExecutionPlan;
 use crate::executor::vtable::VirtualTable;
 use crate::ir::expression::Expression;
 use crate::ir::operator::{Bool, Relational};
+use crate::ir::tree::Snapshot;
 use crate::ir::Node;
 use crate::otm::child_span;
 use sbroad_proc::otm_child_span;
@@ -238,7 +239,10 @@ impl SyntaxNodes {
     /// - nothing was found
     fn get_syntax_node_id(&self, plan_id: usize) -> Result<usize, QueryPlannerError> {
         self.map.get(&plan_id).copied().ok_or_else(|| {
-            QueryPlannerError::CustomError("Current plan node is absent in the map".into())
+            QueryPlannerError::CustomError(format!(
+                "Current plan node ({}) is absent in the map",
+                plan_id
+            ))
         })
     }
 
@@ -424,6 +428,7 @@ pub struct SyntaxPlan<'p> {
     pub(crate) nodes: SyntaxNodes,
     top: Option<usize>,
     plan: &'p ExecutionPlan,
+    snapshot: Snapshot,
 }
 
 #[allow(dead_code)]
@@ -560,10 +565,17 @@ impl<'p> SyntaxPlan<'p> {
                     let left_id = *children.first().ok_or_else(|| {
                         QueryPlannerError::CustomError("Selection has no children.".into())
                     })?;
+                    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)?],
+                        vec![self.nodes.get_syntax_node_id(filter_id)?],
                     );
                     Ok(self.nodes.push_syntax_node(sn))
                 }
@@ -906,6 +918,7 @@ impl<'p> SyntaxPlan<'p> {
             nodes: SyntaxNodes::with_capacity(plan.get_ir_plan().next_id()),
             top: None,
             plan,
+            snapshot: Snapshot::Latest,
         }
     }
 
@@ -916,17 +929,36 @@ impl<'p> SyntaxPlan<'p> {
     /// - Failed to get to the top of the syntax tree
     /// - Failed to move projection nodes under their scans
     #[otm_child_span("syntax.new")]
-    pub fn new(plan: &'p ExecutionPlan, top: usize) -> Result<Self, QueryPlannerError> {
+    pub fn new(
+        plan: &'p ExecutionPlan,
+        top: usize,
+        snapshot: Snapshot,
+    ) -> Result<Self, QueryPlannerError> {
         let mut sp = SyntaxPlan::empty(plan);
+        sp.snapshot = snapshot.clone();
         let ir_plan = plan.get_ir_plan();
 
         // Wrap plan's nodes and preserve their ids.
-        let dft_post = DftPost::new(&top, |node| ir_plan.subtree_iter(node));
-        for (_, id) in dft_post {
-            // it works only for post-order traversal
-            let sn_id = sp.add_plan_node(*id)?;
-            if *id == top {
-                sp.set_top(sn_id)?;
+        match snapshot {
+            Snapshot::Latest => {
+                let dft_post = DftPost::new(&top, |node| ir_plan.subtree_iter(node));
+                for (_, id) in dft_post {
+                    // it works only for post-order traversal
+                    let sn_id = sp.add_plan_node(*id)?;
+                    if *id == top {
+                        sp.set_top(sn_id)?;
+                    }
+                }
+            }
+            Snapshot::Oldest => {
+                let dft_post = DftPost::new(&top, |node| ir_plan.flashback_subtree_iter(node));
+                for (_, id) in dft_post {
+                    // it works only for post-order traversal
+                    let sn_id = sp.add_plan_node(*id)?;
+                    if *id == top {
+                        sp.set_top(sn_id)?;
+                    }
+                }
             }
         }
         sp.move_proj_under_scan()?;
diff --git a/sbroad-core/src/backend/sql/tree/tests.rs b/sbroad-core/src/backend/sql/tree/tests.rs
index 14f59c512d482ae77bb909020e55f44887dbbcb4..efae9280b14f0824fec297b8d1ab44e9ab9a25a8 100644
--- a/sbroad-core/src/backend/sql/tree/tests.rs
+++ b/sbroad-core/src/backend/sql/tree/tests.rs
@@ -6,6 +6,7 @@ use pretty_assertions::assert_eq;
 use crate::backend::sql::tree::{OrderedSyntaxNodes, SyntaxPlan};
 use crate::ir::operator::Bool;
 use crate::ir::relation::{Column, ColumnRole, Table, Type};
+use crate::ir::tree::Snapshot;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 
@@ -49,7 +50,7 @@ fn sql_order_selection() {
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
 
     // test the syntax plan
-    let sp = SyntaxPlan::new(&exec_plan, top_id).unwrap();
+    let sp = SyntaxPlan::new(&exec_plan, top_id, Snapshot::Latest).unwrap();
     let path = Path::new("")
         .join("tests")
         .join("artifactory")
@@ -65,7 +66,7 @@ fn sql_order_selection() {
     let top_id = exec_plan.get_ir_plan().get_top().unwrap();
 
     // get nodes in the sql-convenient order
-    let sp = SyntaxPlan::new(&exec_plan, top_id).unwrap();
+    let sp = SyntaxPlan::new(&exec_plan, top_id, Snapshot::Latest).unwrap();
     let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
     let nodes = ordered.to_syntax_data().unwrap();
     let mut nodes_iter = nodes.into_iter();
diff --git a/sbroad-core/src/executor/engine/mock.rs b/sbroad-core/src/executor/engine/mock.rs
index b49c677b77539ba3660ad12ab693484609bfe120..ed14cc3c04cb326c0dc82a47f71db1e70708139f 100644
--- a/sbroad-core/src/executor/engine/mock.rs
+++ b/sbroad-core/src/executor/engine/mock.rs
@@ -20,6 +20,7 @@ use crate::frontend::sql::ast::AbstractSyntaxTree;
 use crate::ir::function::Function;
 use crate::ir::helpers::RepeatableState;
 use crate::ir::relation::{Column, ColumnRole, Table, Type};
+use crate::ir::tree::Snapshot;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 
@@ -318,7 +319,7 @@ impl Coordinator for RouterRuntimeMock {
         buckets: &Buckets,
     ) -> Result<Box<dyn Any>, QueryPlannerError> {
         let mut result = ProducerResult::new();
-        let sp = SyntaxPlan::new(plan, top_id)?;
+        let sp = SyntaxPlan::new(plan, top_id, Snapshot::Oldest)?;
         let ordered = OrderedSyntaxNodes::try_from(sp)?;
         let nodes = ordered.to_syntax_data()?;
 
diff --git a/sbroad-core/src/executor/tests.rs b/sbroad-core/src/executor/tests.rs
index 98f7167f86738ee04f451dbc1cc3880e4389665b..7554144cf4e4c1638d72ad4fcbbcdd49424cc380 100644
--- a/sbroad-core/src/executor/tests.rs
+++ b/sbroad-core/src/executor/tests.rs
@@ -114,7 +114,7 @@ fn map_reduce_query() {
                         "{} {} {}",
                         r#"SELECT "hash_testing"."product_code""#,
                         r#"FROM "hash_testing""#,
-                        r#"WHERE ("hash_testing"."identification_number", "hash_testing"."product_code") = (?, ?)"#,
+                        r#"WHERE ("hash_testing"."identification_number") = (?) and ("hash_testing"."product_code") = (?)"#,
                     ), vec![param1, param457],
                 )
             )
@@ -332,45 +332,39 @@ WHERE "t3"."id" = 2 AND "t8"."identification_number" = 2"#;
     let param2 = Value::from(2_u64);
     let bucket2 = query.coordinator.determine_bucket_id(&[&param2]);
 
-    expected.rows.extend(vec![
-        vec![
-            Value::String(format!("Execute query on a bucket [{}]", bucket2)),
-            Value::String(
-                String::from(
-                    PatternWithParams::new(
-                        format!(
-                            "{}, {}, {} {}{} {} {} {} {} {} {}{} {} {}{} {} {}",
-                            r#"SELECT "t3"."id""#,
-                            r#""t3"."FIRST_NAME""#,
-                            r#""t8"."identification_number""#,
-                            r#"FROM ("#,
-                            r#"SELECT "test_space"."id", "test_space"."FIRST_NAME""#,
-                            r#"FROM "test_space""#,
-                            r#"WHERE ("test_space"."sysFrom") >= (?) and ("test_space"."sys_op") < (?)"#,
-                            r#"UNION ALL"#,
-                            r#"SELECT "test_space_hist"."id", "test_space_hist"."FIRST_NAME""#,
-                            r#"FROM "test_space_hist""#,
-                            r#"WHERE ("test_space_hist"."sysFrom") <= (?)"#,
-                            r#") as "t3""#,
-                            r#"INNER JOIN"#,
-                            r#"(SELECT COLUMN_1 as "identification_number" FROM (VALUES (?))"#,
-                            r#") as "t8""#,
-                            r#"ON ("t3"."id") = ("t8"."identification_number")"#,
-                            r#"WHERE ("t3"."id", "t3"."id", "t8"."identification_number") = ("t8"."identification_number", ?, ?)"#
-                        ),
-                        vec![
-                            Value::from(0_u64),
-                            Value::from(0_u64),
-                            Value::from(0_u64),
-                            Value::from(2_u64),
-                            Value::from(2_u64),
-                            Value::from(2_u64)
-                        ]
-                    )
-                )
-            )
-        ],
-    ]);
+    expected.rows.extend(vec![vec![
+        Value::String(format!("Execute query on a bucket [{}]", bucket2)),
+        Value::String(String::from(PatternWithParams::new(
+            format!(
+                "{}, {}, {} {}{} {} {} {} {} {} {}{} {} {}{} {} {}",
+                r#"SELECT "t3"."id""#,
+                r#""t3"."FIRST_NAME""#,
+                r#""t8"."identification_number""#,
+                r#"FROM ("#,
+                r#"SELECT "test_space"."id", "test_space"."FIRST_NAME""#,
+                r#"FROM "test_space""#,
+                r#"WHERE ("test_space"."sys_op") < (?) and ("test_space"."sysFrom") >= (?)"#,
+                r#"UNION ALL"#,
+                r#"SELECT "test_space_hist"."id", "test_space_hist"."FIRST_NAME""#,
+                r#"FROM "test_space_hist""#,
+                r#"WHERE ("test_space_hist"."sysFrom") <= (?)"#,
+                r#") as "t3""#,
+                r#"INNER JOIN"#,
+                r#"(SELECT COLUMN_1 as "identification_number" FROM (VALUES (?))"#,
+                r#") as "t8""#,
+                r#"ON ("t3"."id") = ("t8"."identification_number")"#,
+                r#"WHERE ("t3"."id") = (?) and ("t8"."identification_number") = (?)"#
+            ),
+            vec![
+                Value::from(0_u64),
+                Value::from(0_u64),
+                Value::from(0_u64),
+                Value::from(2_u64),
+                Value::from(2_u64),
+                Value::from(2_u64),
+            ],
+        ))),
+    ]]);
     assert_eq!(expected, result);
 }
 
diff --git a/sbroad-core/src/executor/tests/between.rs b/sbroad-core/src/executor/tests/between.rs
index 6514471781910d121a55ded6ba452d974eeae808..5be94415fe893f301f405070af6b5ccf96b7da94 100644
--- a/sbroad-core/src/executor/tests/between.rs
+++ b/sbroad-core/src/executor/tests/between.rs
@@ -57,12 +57,12 @@ fn between1_test() {
             format!(
                 "{} {} {}",
                 r#"SELECT "t"."identification_number" FROM "hash_testing" as "t""#,
-                r#"WHERE ("t"."identification_number") <= (SELECT COLUMN_1 as "id" FROM (VALUES (?)))"#,
-                r#"and ("t"."identification_number") >= (?)"#,
+                r#"WHERE ("t"."identification_number") >= (?)"#,
+                r#"and ("t"."identification_number") <= (SELECT COLUMN_1 as "id" FROM (VALUES (?)))"#,
             ),
             vec![
-                Value::from(2_u64),
                 Value::from(1_u64),
+                Value::from(2_u64),
             ],
         ))),
     ]]);
@@ -123,14 +123,14 @@ fn between2_test() {
             format!(
                 "{} {} {}",
                 r#"SELECT "t"."identification_number" FROM "hash_testing" as "t""#,
-                r#"WHERE (SELECT COLUMN_1 as "id" FROM (VALUES (?))) <= (?)"#,
-                r#"and (SELECT COLUMN_2 as "id" FROM (VALUES (?))) >= (?)"#,
+                r#"WHERE (SELECT COLUMN_1 as "id" FROM (VALUES (?))) >= (?)"#,
+                r#"and (SELECT COLUMN_2 as "id" FROM (VALUES (?))) <= (?)"#,
             ),
             vec![
-                Value::from(2_u64),
-                Value::from(3_u64),
                 Value::from(2_u64),
                 Value::from(1_u64),
+                Value::from(2_u64),
+                Value::from(3_u64),
             ],
         ))),
     ]]);
diff --git a/sbroad-core/src/executor/tests/bucket_id.rs b/sbroad-core/src/executor/tests/bucket_id.rs
index 17abd756186c1d7c1af9452436531204bdd0bd7c..6ea2280ddb363edea0c9e0367bc639bd8de1825c 100644
--- a/sbroad-core/src/executor/tests/bucket_id.rs
+++ b/sbroad-core/src/executor/tests/bucket_id.rs
@@ -55,7 +55,7 @@ fn bucket2_test() {
             format!(
                 "{} {}",
                 r#"SELECT "t1"."a", "t1"."bucket_id", "t1"."b" FROM "t1""#,
-                r#"WHERE ("t1"."a", "t1"."b") = (?, ?)"#,
+                r#"WHERE ("t1"."a") = (?) and ("t1"."b") = (?)"#,
             ),
             vec![param1, param2],
         ))),
diff --git a/sbroad-core/src/executor/tests/not_eq.rs b/sbroad-core/src/executor/tests/not_eq.rs
index f9d134de7cfca7afdbbc1f349fc4106bcf013295..a2f7ab4565622169e4f0428b9bcefda1cf8ec328 100644
--- a/sbroad-core/src/executor/tests/not_eq.rs
+++ b/sbroad-core/src/executor/tests/not_eq.rs
@@ -41,9 +41,9 @@ fn not_eq1_test() {
             format!(
                 "{} {}",
                 r#"SELECT "t"."identification_number" FROM "hash_testing" as "t""#,
-                r#"WHERE ("t"."product_code") <> (?) and ("t"."identification_number") <> (?)"#,
+                r#"WHERE ("t"."identification_number") <> (?) and ("t"."product_code") <> (?)"#,
             ),
-            vec![Value::from(2_u64), Value::from(1_u64)],
+            vec![Value::from(1_u64), Value::from(2_u64)],
         ))),
     ]]);
     assert_eq!(expected, result);
diff --git a/sbroad-core/src/ir.rs b/sbroad-core/src/ir.rs
index abdab500c92525b40b1944666e66b0c3a6e2c454..bb6a3f89c6620485ccc6d00dfa6912bca59ff052 100644
--- a/sbroad-core/src/ir.rs
+++ b/sbroad-core/src/ir.rs
@@ -28,7 +28,14 @@ pub mod value;
 #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
 pub struct TreeMap(HashMap<usize, usize, RepeatableState>);
 
+impl Default for TreeMap {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
 impl TreeMap {
+    #[must_use]
     pub fn new() -> Self {
         Self(HashMap::with_hasher(RepeatableState))
     }
@@ -37,16 +44,23 @@ impl TreeMap {
         self.0.insert(new_id, old_id);
     }
 
-    pub fn get(&self, new_id: usize) -> Option<usize> {
-        self.0.get(&new_id).copied()
+    #[must_use]
+    pub fn get(&self, new_id: &usize) -> Option<&usize> {
+        self.0.get(new_id)
     }
 
-    pub fn get_oldest(&self, new_id: usize) -> usize {
-        let mut id = new_id;
-        while let Some(old_id) = self.get(id) {
-            id = old_id;
+    #[must_use]
+    pub fn get_oldest(&self, new_id: &usize) -> Option<&usize> {
+        match self.0.get_key_value(new_id) {
+            None => None,
+            Some((id, _)) => {
+                let mut current = id;
+                while let Some(parent) = self.get(current) {
+                    current = parent;
+                }
+                Some(current)
+            }
         }
-        id
     }
 }
 
@@ -138,10 +152,9 @@ pub struct Plan {
     /// The flag is enabled if user wants to get a query plan only.
     /// In this case we don't need to execute query.
     is_explain: bool,
-    /// The undo log is used to track the changes in the plan tree
-    /// during the optimization process. It is used to restore the
-    /// original subtree after the optimization (if it is needed).
-    undo: TreeMap,
+    /// The undo log keeps the history of the plan transformations. It can
+    /// be used to revert the plan subtree to some previous snapshot if needed.
+    pub(crate) undo: TreeMap,
 }
 
 impl Default for Plan {
diff --git a/sbroad-core/src/ir/transformation.rs b/sbroad-core/src/ir/transformation.rs
index c5ffa20462030a1ca14a84295e1de164fdb73640..28cb3401a316d4044e1ea7f3b296b114e6e8ed97 100644
--- a/sbroad-core/src/ir/transformation.rs
+++ b/sbroad-core/src/ir/transformation.rs
@@ -95,7 +95,7 @@ impl Plan {
                 _ => continue,
             };
             if old_tree_id != new_tree_id {
-                self.undo.add(new_tree_id, old_tree_id);
+                self.undo.add(old_tree_id, new_tree_id);
             }
             let rel = self.get_mut_relation_node(*id)?;
             match rel {
diff --git a/sbroad-core/src/ir/transformation/bool_in/tests.rs b/sbroad-core/src/ir/transformation/bool_in/tests.rs
index feccf6b7426f411c67f51f1d2b64814c90690c18..6de0158fa38a0dd1d68935d5b50d5baddd5ba3d0 100644
--- a/sbroad-core/src/ir/transformation/bool_in/tests.rs
+++ b/sbroad-core/src/ir/transformation/bool_in/tests.rs
@@ -1,5 +1,5 @@
 use crate::backend::sql::ir::PatternWithParams;
-use crate::ir::transformation::helpers::sql_to_sql;
+use crate::ir::transformation::helpers::check_transformation;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 use pretty_assertions::assert_eq;
@@ -20,7 +20,10 @@ fn bool_in1() {
         vec![Value::from(1_u64), Value::from(2_u64), Value::from(3_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &replace_in_operator), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &replace_in_operator),
+        expected
+    );
 }
 
 #[test]
@@ -43,7 +46,10 @@ fn bool_in2() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &replace_in_operator), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &replace_in_operator),
+        expected
+    );
 }
 
 #[test]
@@ -58,5 +64,8 @@ fn bool_in3() {
         vec![Value::from(1_u64), Value::from(2_u64), Value::from(3_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &replace_in_operator), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &replace_in_operator),
+        expected
+    );
 }
diff --git a/sbroad-core/src/ir/transformation/dnf/tests.rs b/sbroad-core/src/ir/transformation/dnf/tests.rs
index 37b671f120af0f140a3bd1668ea9434644fcd551..9943e953186cb4c5f2acf1989510cd84b95c9ffd 100644
--- a/sbroad-core/src/ir/transformation/dnf/tests.rs
+++ b/sbroad-core/src/ir/transformation/dnf/tests.rs
@@ -1,5 +1,5 @@
 use crate::backend::sql::ir::PatternWithParams;
-use crate::ir::transformation::helpers::sql_to_sql;
+use crate::ir::transformation::helpers::check_transformation;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 use pretty_assertions::assert_eq;
@@ -28,7 +28,7 @@ fn dnf1() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &set_dnf), expected);
+    assert_eq!(check_transformation(input, vec![], &set_dnf), expected);
 }
 
 #[test]
@@ -54,7 +54,7 @@ fn dnf2() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &set_dnf), expected);
+    assert_eq!(check_transformation(input, vec![], &set_dnf), expected);
 }
 
 #[test]
@@ -75,7 +75,7 @@ fn dnf3() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &set_dnf), expected);
+    assert_eq!(check_transformation(input, vec![], &set_dnf), expected);
 }
 
 #[test]
@@ -96,7 +96,7 @@ fn dnf4() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &set_dnf), expected);
+    assert_eq!(check_transformation(input, vec![], &set_dnf), expected);
 }
 
 #[test]
@@ -117,7 +117,7 @@ fn dnf5() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &set_dnf), expected);
+    assert_eq!(check_transformation(input, vec![], &set_dnf), expected);
 }
 
 #[test]
@@ -133,5 +133,5 @@ fn dnf6() {
         vec![Value::from(1_u64), Value::from(1_u64), Value::from(2_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &set_dnf), expected);
+    assert_eq!(check_transformation(input, vec![], &set_dnf), expected);
 }
diff --git a/sbroad-core/src/ir/transformation/equality_propagation/tests.rs b/sbroad-core/src/ir/transformation/equality_propagation/tests.rs
index 7f1b0fdb5f848c9945a55f0825c05534405069db..4a7f7ddcf830475d7ee49217baf41e0e939b91d2 100644
--- a/sbroad-core/src/ir/transformation/equality_propagation/tests.rs
+++ b/sbroad-core/src/ir/transformation/equality_propagation/tests.rs
@@ -1,5 +1,5 @@
 use crate::backend::sql::ir::PatternWithParams;
-use crate::ir::transformation::helpers::sql_to_sql;
+use crate::ir::transformation::helpers::check_transformation;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 use pretty_assertions::assert_eq;
@@ -28,7 +28,10 @@ fn equality_propagation1() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &derive_equalities), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &derive_equalities),
+        expected
+    );
 }
 
 #[test]
@@ -41,7 +44,10 @@ fn equality_propagation2() {
         vec![Value::Null, Value::Null],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &derive_equalities), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &derive_equalities),
+        expected
+    );
 }
 
 #[test]
@@ -58,7 +64,10 @@ fn equality_propagation3() {
         vec![Value::from(1_u64), Value::Null, Value::Null],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &derive_equalities), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &derive_equalities),
+        expected
+    );
 }
 
 #[test]
@@ -81,7 +90,10 @@ fn equality_propagation4() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &derive_equalities), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &derive_equalities),
+        expected
+    );
 }
 
 #[test]
@@ -106,5 +118,8 @@ fn equality_propagation5() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &derive_equalities), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &derive_equalities),
+        expected
+    );
 }
diff --git a/sbroad-core/src/ir/transformation/helpers.rs b/sbroad-core/src/ir/transformation/helpers.rs
index 424d23287c7c82d8fbac967cbefa0cf858407008..41d921892f3442845765a648c30f06f24996bc31 100644
--- a/sbroad-core/src/ir/transformation/helpers.rs
+++ b/sbroad-core/src/ir/transformation/helpers.rs
@@ -7,6 +7,7 @@ use crate::executor::engine::mock::RouterConfigurationMock;
 use crate::executor::ir::ExecutionPlan;
 use crate::frontend::sql::ast::AbstractSyntaxTree;
 use crate::frontend::Ast;
+use crate::ir::tree::Snapshot;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 
@@ -40,7 +41,7 @@ pub fn sql_to_ir(query: &str, params: Vec<Value>) -> Plan {
 /// # Panics
 ///   if query is not correct
 #[allow(dead_code)]
-pub fn sql_to_sql(
+pub fn check_transformation(
     query: &str,
     params: Vec<Value>,
     f_transform: &dyn Fn(&mut Plan),
@@ -49,7 +50,7 @@ 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 sp = SyntaxPlan::new(&ex_plan, top_id).unwrap();
+    let sp = SyntaxPlan::new(&ex_plan, top_id, Snapshot::Latest).unwrap();
     let ordered = OrderedSyntaxNodes::try_from(sp).unwrap();
     let nodes = ordered.to_syntax_data().unwrap();
     ex_plan.to_sql(&nodes, &Buckets::All).unwrap()
diff --git a/sbroad-core/src/ir/transformation/merge_tuples/tests.rs b/sbroad-core/src/ir/transformation/merge_tuples/tests.rs
index 22c8361e50f475194a0b054b47aecf5a80e79669..11e9c8ffdd9dec6dd5c7413dda7462f10fdd53b9 100644
--- a/sbroad-core/src/ir/transformation/merge_tuples/tests.rs
+++ b/sbroad-core/src/ir/transformation/merge_tuples/tests.rs
@@ -1,5 +1,5 @@
 use crate::backend::sql::ir::PatternWithParams;
-use crate::ir::transformation::helpers::sql_to_sql;
+use crate::ir::transformation::helpers::check_transformation;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 use pretty_assertions::assert_eq;
@@ -25,7 +25,7 @@ fn merge_tuples1() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &merge_tuples), expected);
+    assert_eq!(check_transformation(input, vec![], &merge_tuples), expected);
 }
 
 #[test]
@@ -50,7 +50,7 @@ fn merge_tuples2() {
         ],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &merge_tuples), expected);
+    assert_eq!(check_transformation(input, vec![], &merge_tuples), expected);
 }
 
 #[test]
@@ -61,7 +61,7 @@ fn merge_tuples3() {
         vec![Value::Boolean(true)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &merge_tuples), expected);
+    assert_eq!(check_transformation(input, vec![], &merge_tuples), expected);
 }
 
 #[test]
@@ -75,7 +75,7 @@ fn merge_tuples4() {
         vec![Value::from(1_u64), Value::from(2_u64), Value::from(3_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &merge_tuples), expected);
+    assert_eq!(check_transformation(input, vec![], &merge_tuples), expected);
 }
 
 #[test]
@@ -90,7 +90,7 @@ fn merge_tuples5() {
         vec![Value::from(1_u64), Value::from(2_u64), Value::from(3_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &merge_tuples), expected);
+    assert_eq!(check_transformation(input, vec![], &merge_tuples), expected);
 }
 
 #[test]
@@ -104,5 +104,5 @@ fn merge_tuples6() {
         vec![Value::from(2_u64), Value::from(1_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &merge_tuples), expected);
+    assert_eq!(check_transformation(input, vec![], &merge_tuples), expected);
 }
diff --git a/sbroad-core/src/ir/transformation/split_columns/tests.rs b/sbroad-core/src/ir/transformation/split_columns/tests.rs
index 7eaaf0a762323495506b8e1865f84a2ed3e8271e..02ad99fe980380a2a6c6597f3dd041bd18fcc9e2 100644
--- a/sbroad-core/src/ir/transformation/split_columns/tests.rs
+++ b/sbroad-core/src/ir/transformation/split_columns/tests.rs
@@ -2,7 +2,7 @@ use crate::backend::sql::ir::PatternWithParams;
 use crate::executor::engine::mock::RouterConfigurationMock;
 use crate::frontend::sql::ast::AbstractSyntaxTree;
 use crate::frontend::Ast;
-use crate::ir::transformation::helpers::sql_to_sql;
+use crate::ir::transformation::helpers::check_transformation;
 use crate::ir::value::Value;
 use crate::ir::Plan;
 use pretty_assertions::assert_eq;
@@ -19,7 +19,10 @@ fn split_columns1() {
         vec![Value::from(1_u64), Value::from(2_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &split_columns), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &split_columns),
+        expected
+    );
 }
 
 #[test]
@@ -30,7 +33,10 @@ fn split_columns2() {
         vec![Value::from(1_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &split_columns), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &split_columns),
+        expected
+    );
 }
 
 #[test]
@@ -61,7 +67,10 @@ fn split_columns4() {
         vec![Value::from(1_u64), Value::from(2_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &split_columns), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &split_columns),
+        expected
+    );
 }
 
 #[test]
@@ -76,5 +85,8 @@ fn split_columns5() {
         vec![Value::from(1_u64), Value::from(2_u64), Value::from(2_u64)],
     );
 
-    assert_eq!(sql_to_sql(input, vec![], &split_columns), expected);
+    assert_eq!(
+        check_transformation(input, vec![], &split_columns),
+        expected
+    );
 }
diff --git a/sbroad-core/src/ir/tree.rs b/sbroad-core/src/ir/tree.rs
index ea174a34ae42facd6bd7a9f27c8ddf47487e005f..d0df786dc320a14ac97a4234b94ae3c62f654467 100644
--- a/sbroad-core/src/ir/tree.rs
+++ b/sbroad-core/src/ir/tree.rs
@@ -13,6 +13,14 @@ trait PlanTreeIterator<'plan>: TreeIterator<'plan> {
     fn get_plan(&self) -> &'plan Plan;
 }
 
+/// A snapshot describes the version of the plan
+/// subtree to iterate over.
+#[derive(Debug, Clone)]
+pub enum Snapshot {
+    Latest,
+    Oldest,
+}
+
 pub mod and;
 pub mod eq_class;
 pub mod expression;
diff --git a/sbroad-core/src/ir/tree/and.rs b/sbroad-core/src/ir/tree/and.rs
index f38259e07957ba52a258feaddf13603c06c27d71..1c6c8377f98fb2217f031f0352398089b220bbbe 100644
--- a/sbroad-core/src/ir/tree/and.rs
+++ b/sbroad-core/src/ir/tree/and.rs
@@ -10,6 +10,7 @@ trait AndTreeIterator<'nodes>: TreeIterator<'nodes> {}
 /// Children iterator for "and"-ed expression chains.
 ///
 /// The iterator returns the next child for the chained `Bool::And` nodes.
+#[allow(clippy::module_name_repetitions)]
 #[derive(Debug)]
 pub struct AndIterator<'n> {
     current: &'n usize,
diff --git a/sbroad-core/src/ir/tree/eq_class.rs b/sbroad-core/src/ir/tree/eq_class.rs
index a96ad63b8c1dc413ea42230196ed748c9ca5ce28..c8febae73d0f8fc8630c8ad0a48f3b7525cccae9 100644
--- a/sbroad-core/src/ir/tree/eq_class.rs
+++ b/sbroad-core/src/ir/tree/eq_class.rs
@@ -11,6 +11,7 @@ trait EqClassTreeIterator<'nodes>: TreeIterator<'nodes> {}
 ///
 /// The iterator returns the next child for the chained `Bool::And`
 /// and `Bool::Eq` nodes.
+#[allow(clippy::module_name_repetitions)]
 #[derive(Debug)]
 pub struct EqClassIterator<'n> {
     current: &'n usize,
diff --git a/sbroad-core/src/ir/tree/expression.rs b/sbroad-core/src/ir/tree/expression.rs
index aeafaebc88ee38e67f817e5fdcc689ba1ece51cf..f46e4ebb6958568c21c83df29891dc74e870cd37 100644
--- a/sbroad-core/src/ir/tree/expression.rs
+++ b/sbroad-core/src/ir/tree/expression.rs
@@ -12,6 +12,7 @@ trait ExpressionTreeIterator<'nodes>: TreeIterator<'nodes> {
 ///
 /// The iterator returns the next child for expression
 /// nodes. It is required to use `traversal` crate.
+#[allow(clippy::module_name_repetitions)]
 #[derive(Debug)]
 pub struct ExpressionIterator<'n> {
     current: &'n usize,
diff --git a/sbroad-core/src/ir/tree/subtree.rs b/sbroad-core/src/ir/tree/subtree.rs
index 0868168be519aace8af1ad4b2c1200612615d8d6..17845d033597707b0be8da3fa517020113b89f16 100644
--- a/sbroad-core/src/ir/tree/subtree.rs
+++ b/sbroad-core/src/ir/tree/subtree.rs
@@ -1,7 +1,7 @@
 use std::cell::RefCell;
 use std::cmp::Ordering;
 
-use super::{PlanTreeIterator, TreeIterator};
+use super::{PlanTreeIterator, Snapshot, TreeIterator};
 use crate::ir::expression::Expression;
 use crate::ir::operator::Relational;
 use crate::ir::{Node, Nodes, Plan};
@@ -9,6 +9,7 @@ use crate::ir::{Node, Nodes, Plan};
 trait SubtreePlanIterator<'plan>: PlanTreeIterator<'plan> {}
 
 /// Expression and relational nodes iterator.
+#[allow(clippy::module_name_repetitions)]
 #[derive(Debug)]
 pub struct SubtreeIterator<'plan> {
     current: &'plan usize,
@@ -42,7 +43,7 @@ impl<'plan> Iterator for SubtreeIterator<'plan> {
     type Item = &'plan usize;
 
     fn next(&mut self) -> Option<Self::Item> {
-        subtree_next(self)
+        subtree_next(self, &Snapshot::Latest)
     }
 }
 
@@ -57,8 +58,66 @@ impl<'plan> Plan {
     }
 }
 
+/// Expression and relational nodes flashback iterator.
+/// It uses the UNDO transformation log to go back to the
+/// original state of some subtrees in the plan (selections
+/// at the moment).
+#[derive(Debug)]
+pub struct FlashbackSubtreeIterator<'plan> {
+    current: &'plan usize,
+    child: RefCell<usize>,
+    plan: &'plan Plan,
+}
+
+impl<'nodes> TreeIterator<'nodes> for FlashbackSubtreeIterator<'nodes> {
+    fn get_current(&self) -> &'nodes usize {
+        self.current
+    }
+
+    fn get_child(&self) -> &RefCell<usize> {
+        &self.child
+    }
+
+    fn get_nodes(&self) -> &'nodes Nodes {
+        &self.plan.nodes
+    }
+}
+
+impl<'plan> PlanTreeIterator<'plan> for FlashbackSubtreeIterator<'plan> {
+    fn get_plan(&self) -> &'plan Plan {
+        self.plan
+    }
+}
+
+impl<'plan> SubtreePlanIterator<'plan> for FlashbackSubtreeIterator<'plan> {}
+
+impl<'plan> Iterator for FlashbackSubtreeIterator<'plan> {
+    type Item = &'plan usize;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        subtree_next(self, &Snapshot::Oldest)
+    }
+}
+
+impl<'plan> Plan {
+    #[must_use]
+    pub fn flashback_subtree_iter(
+        &'plan self,
+        current: &'plan usize,
+    ) -> FlashbackSubtreeIterator<'plan> {
+        FlashbackSubtreeIterator {
+            current,
+            child: RefCell::new(0),
+            plan: self,
+        }
+    }
+}
+
 #[allow(clippy::too_many_lines)]
-fn subtree_next<'plan>(iter: &mut impl SubtreePlanIterator<'plan>) -> Option<&'plan usize> {
+fn subtree_next<'plan>(
+    iter: &mut impl SubtreePlanIterator<'plan>,
+    snapshot: &Snapshot,
+) -> Option<&'plan usize> {
     if let Some(child) = iter.get_nodes().arena.get(*iter.get_current()) {
         return match child {
             Node::Parameter => None,
@@ -198,9 +257,17 @@ fn subtree_next<'plan>(iter: &mut impl SubtreePlanIterator<'plan>) -> Option<&'p
                         Ordering::Less => {
                             return children.get(step);
                         }
-                        Ordering::Equal => {
-                            return Some(filter);
-                        }
+                        Ordering::Equal => match snapshot {
+                            Snapshot::Latest => Some(filter),
+                            Snapshot::Oldest => {
+                                return Some(
+                                    iter.get_plan()
+                                        .undo
+                                        .get_oldest(filter)
+                                        .map_or_else(|| filter, |id| id),
+                                );
+                            }
+                        },
                         Ordering::Greater => None,
                     }
                 }
diff --git a/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection.yaml b/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection.yaml
index 19a2aa7daeef5e5f459f520980b57febe9a0e67e..a1125e3312af24be929694516442468785bbd1b1 100644
--- a/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection.yaml
+++ b/sbroad-core/tests/artifactory/backend/sql/tree/sql_order_selection.yaml
@@ -113,3 +113,4 @@ relations:
 slices: ~
 top: 16
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/distribution/join_unite_keys.yaml b/sbroad-core/tests/artifactory/ir/distribution/join_unite_keys.yaml
index b1ac3d0077e06e447beb9e9321be7d4808625275..a5eec7cf424931e638648b6846f198ac3fd62e6a 100644
--- a/sbroad-core/tests/artifactory/ir/distribution/join_unite_keys.yaml
+++ b/sbroad-core/tests/artifactory/ir/distribution/join_unite_keys.yaml
@@ -171,3 +171,4 @@ relations:
 slices: ~
 top: 28
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_1.yaml b/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_1.yaml
index 0646bb3bf3b0e7ae4461aa47063be71e55f424af..2ff4e07729b9e5fb20635eedfab65719da3ab7d6 100644
--- a/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_1.yaml
+++ b/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_1.yaml
@@ -99,3 +99,4 @@ relations:
 slices: ~
 top: 15
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_2.yaml b/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_2.yaml
index 82494146138c4e242088b64d849b7fe0c2a4f3d0..8e1c4a050b0956d97a3027ef9a24527f2afa7806 100644
--- a/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_2.yaml
+++ b/sbroad-core/tests/artifactory/ir/distribution/shrink_dist_key_2.yaml
@@ -88,3 +88,4 @@ relations:
 slices: ~
 top: 13
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/distribution/shuffle_dist_key.yaml b/sbroad-core/tests/artifactory/ir/distribution/shuffle_dist_key.yaml
index d2f81b5ca91593638c6e68dec69b5cc479a92d8f..2c3200dc93bb47274114e878f42253c5aa6f8b79 100644
--- a/sbroad-core/tests/artifactory/ir/distribution/shuffle_dist_key.yaml
+++ b/sbroad-core/tests/artifactory/ir/distribution/shuffle_dist_key.yaml
@@ -99,3 +99,4 @@ relations:
 slices: ~
 top: 15
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/distribution/union_fallback_to_random.yaml b/sbroad-core/tests/artifactory/ir/distribution/union_fallback_to_random.yaml
index e10eccccdd87bb494eb81b58493d4c58e4f71e7c..0365fd8300ca088ff0a9097c9c3a2daecafae7d1 100644
--- a/sbroad-core/tests/artifactory/ir/distribution/union_fallback_to_random.yaml
+++ b/sbroad-core/tests/artifactory/ir/distribution/union_fallback_to_random.yaml
@@ -115,3 +115,4 @@ relations:
 slices: ~
 top: 17
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/distribution/union_preserve_dist.yaml b/sbroad-core/tests/artifactory/ir/distribution/union_preserve_dist.yaml
index 60ae5e3b6af972c0226ca3c8a5f8f4670d53df0c..d5e530d7c0a2c1867dea0d1960a582ee0cdfc700 100644
--- a/sbroad-core/tests/artifactory/ir/distribution/union_preserve_dist.yaml
+++ b/sbroad-core/tests/artifactory/ir/distribution/union_preserve_dist.yaml
@@ -115,3 +115,4 @@ relations:
 slices: ~
 top: 17
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/join.yaml b/sbroad-core/tests/artifactory/ir/operator/join.yaml
index b1ac3d0077e06e447beb9e9321be7d4808625275..a5eec7cf424931e638648b6846f198ac3fd62e6a 100644
--- a/sbroad-core/tests/artifactory/ir/operator/join.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/join.yaml
@@ -171,3 +171,4 @@ relations:
 slices: ~
 top: 28
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/output_aliases.yaml b/sbroad-core/tests/artifactory/ir/operator/output_aliases.yaml
index 0e2235de84453c4796686c2cd13a3fe119d05160..fd3fa6fe03b65ab8538fe8df6f32f09592cca11e 100644
--- a/sbroad-core/tests/artifactory/ir/operator/output_aliases.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/output_aliases.yaml
@@ -44,3 +44,4 @@ relations:
     name: t
 slices: ~
 top: 5
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/output_aliases_duplicates.yaml b/sbroad-core/tests/artifactory/ir/operator/output_aliases_duplicates.yaml
index febed528f0d0999cd93945c6f92d41b8a5de2092..1bbafd3ef94cad94a1f46da2a03f746a7027b56b 100644
--- a/sbroad-core/tests/artifactory/ir/operator/output_aliases_duplicates.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/output_aliases_duplicates.yaml
@@ -44,3 +44,4 @@ relations:
     name: t
 slices: ~
 top: 5
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/output_aliases_oor.yaml b/sbroad-core/tests/artifactory/ir/operator/output_aliases_oor.yaml
index 33d04e1e732eba193e97b97e600e67c3dd2eb5e0..159ff0c773002338aeb8b50d3974f580b5ef5a46 100644
--- a/sbroad-core/tests/artifactory/ir/operator/output_aliases_oor.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/output_aliases_oor.yaml
@@ -35,3 +35,4 @@ relations:
     name: t
 slices: ~
 top: 3
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/output_aliases_unsupported_type.yaml b/sbroad-core/tests/artifactory/ir/operator/output_aliases_unsupported_type.yaml
index a39463aae4caf3823b1713bb9541deba9ed7354a..30cc8279ce2605eaf63fbb797903610993b48c99 100644
--- a/sbroad-core/tests/artifactory/ir/operator/output_aliases_unsupported_type.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/output_aliases_unsupported_type.yaml
@@ -40,3 +40,4 @@ relations:
     name: t
 slices: ~
 top: 4
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/projection.yaml b/sbroad-core/tests/artifactory/ir/operator/projection.yaml
index 965a3d0c2aa87159fd07202d9a62364f74aab784..49e42253cf45f100e890f1ec1045655da0c410e0 100644
--- a/sbroad-core/tests/artifactory/ir/operator/projection.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/projection.yaml
@@ -74,3 +74,4 @@ relations:
 slices: ~
 top: 9
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/scan_rel.yaml b/sbroad-core/tests/artifactory/ir/operator/scan_rel.yaml
index 314dc8b09ff502dffb40b681445ee9107251a692..a46ea0c1f9da25f32e0cde903aad4a072820da15 100644
--- a/sbroad-core/tests/artifactory/ir/operator/scan_rel.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/scan_rel.yaml
@@ -73,3 +73,4 @@ relations:
 slices: ~
 top: 9
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/selection.yaml b/sbroad-core/tests/artifactory/ir/operator/selection.yaml
index dafbec9d8d734b1b626725aece3f48c9c36a4e73..75090997341eebb1e00277c66bf0589fbecf8684 100644
--- a/sbroad-core/tests/artifactory/ir/operator/selection.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/selection.yaml
@@ -149,3 +149,4 @@ relations:
 slices: ~
 top: 23
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/selection_with_sub_query.yaml b/sbroad-core/tests/artifactory/ir/operator/selection_with_sub_query.yaml
index 323c7fce30f77a469b4c10495a0102a10974d3bd..5705e4195f6458347f0baebab825c601144be966 100644
--- a/sbroad-core/tests/artifactory/ir/operator/selection_with_sub_query.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/selection_with_sub_query.yaml
@@ -150,3 +150,4 @@ relations:
 slices: ~
 top: 24
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/operator/sub_query.yaml b/sbroad-core/tests/artifactory/ir/operator/sub_query.yaml
index 60b9c0588381157959fe24af234ddb8b89d7ff11..a01aaf056611bad3491dbc68269c127236cf36f8 100644
--- a/sbroad-core/tests/artifactory/ir/operator/sub_query.yaml
+++ b/sbroad-core/tests/artifactory/ir/operator/sub_query.yaml
@@ -82,3 +82,4 @@ relations:
 slices: ~
 top: 11
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/plan_no_top.yaml b/sbroad-core/tests/artifactory/ir/plan_no_top.yaml
index bb091a3b4fc9658dc5e9e6f153f9f525c16baf48..d35a5a3d54b39a87b1020d1a407651d4e38a4bce 100644
--- a/sbroad-core/tests/artifactory/ir/plan_no_top.yaml
+++ b/sbroad-core/tests/artifactory/ir/plan_no_top.yaml
@@ -35,3 +35,4 @@ relations:
 slices: ~
 top: ~
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/plan_oor_top.yaml b/sbroad-core/tests/artifactory/ir/plan_oor_top.yaml
index 652b2be063343c5c8f27efe54bf973fa22f8769a..c4bb1f225c7d9e69133787db0183b73476bd283d 100644
--- a/sbroad-core/tests/artifactory/ir/plan_oor_top.yaml
+++ b/sbroad-core/tests/artifactory/ir/plan_oor_top.yaml
@@ -35,3 +35,4 @@ relations:
 slices: ~
 top: 42
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml b/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml
index 7e7ab85177d06ec372c788ddda6e28355d725bcb..a24ad86786ff0c12fdb0ae31b3b4fd2f75559b1f 100644
--- a/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml
+++ b/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml
@@ -199,3 +199,4 @@ slices:
      - 30
 top: 26
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml b/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml
index ddac69bf957cad7183dcb872d2e96e1e2191a874..a0b1102c93afbd5b0be45aaddbbaf5c69964a215 100644
--- a/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml
+++ b/sbroad-core/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml
@@ -218,3 +218,4 @@ slices:
     - 32
 top: 28
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml b/sbroad-core/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml
index c7fda607c315f77c9d62b4b99687da451a6f4de9..19c59a6245bf0c93e68329612ad5ae7a7f8e56d2 100644
--- a/sbroad-core/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml
+++ b/sbroad-core/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml
@@ -175,3 +175,4 @@ relations:
 slices: ~
 top: 24
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml b/sbroad-core/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml
index 138593e3ab48c82b3034a71f736e78d4d36ec3c1..6f2aa7c28ea124859df233c1c103863e53be5f52 100644
--- a/sbroad-core/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml
+++ b/sbroad-core/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml
@@ -347,3 +347,4 @@ slices:
     - 54
 top: 46
 is_explain: false
+undo: {}
diff --git a/sbroad-core/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml b/sbroad-core/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml
index bd8470931001d8df6445cf90379759c89869deb7..52c411d2368e9dae2bf77dc95147009e3b19f25d 100644
--- a/sbroad-core/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml
+++ b/sbroad-core/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml
@@ -206,3 +206,4 @@ slices:
     - 30
 top: 26
 is_explain: false
+undo: {}