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