From 015556a0dbcd2ac6b1a664a986972638ff646996 Mon Sep 17 00:00:00 2001 From: EmirVildanov <reddog201030@gmail.com> Date: Tue, 3 Sep 2024 19:05:25 +0300 Subject: [PATCH] feat: add logic of correct local SQL generation for the case of asterisk (not in a view of references, but as "*") --- sbroad-core/src/backend/sql/ir.rs | 7 + .../src/backend/sql/ir/tests/inner_join.rs | 4 +- .../src/backend/sql/ir/tests/projection.rs | 12 +- sbroad-core/src/backend/sql/tree.rs | 159 ++++++++++++++++-- sbroad-core/src/executor/tests.rs | 41 ++--- sbroad-core/src/executor/tests/bucket_id.rs | 4 +- .../src/executor/tests/empty_motion.rs | 2 +- sbroad-core/src/executor/tests/exec_plan.rs | 18 +- sbroad-core/src/frontend/sql.rs | 21 ++- sbroad-core/src/frontend/sql/ir.rs | 1 + sbroad-core/src/ir/aggregates.rs | 1 + sbroad-core/src/ir/expression.rs | 49 +++++- sbroad-core/src/ir/helpers.rs | 3 +- sbroad-core/src/ir/helpers/tests.rs | 96 +++++------ sbroad-core/src/ir/operator.rs | 28 +-- .../ir/transformation/equality_propagation.rs | 6 +- .../equality_propagation/tests.rs | 4 +- .../ir/transformation/not_push_down/tests.rs | 10 +- .../transformation/redistribution/eq_cols.rs | 5 +- .../transformation/redistribution/groupby.rs | 8 +- 20 files changed, 337 insertions(+), 142 deletions(-) diff --git a/sbroad-core/src/backend/sql/ir.rs b/sbroad-core/src/backend/sql/ir.rs index 51bd0da8e..ce28164de 100644 --- a/sbroad-core/src/backend/sql/ir.rs +++ b/sbroad-core/src/backend/sql/ir.rs @@ -308,6 +308,13 @@ impl ExecutionPlan { match data { // TODO: should we care about plans without projections? // Or they should be treated as invalid? + SyntaxData::Asterisk(relation_name) => { + if let Some(relation_name) = relation_name { + push_identifier(&mut sql, relation_name.as_str()); + sql.push('.') + } + sql.push('*') + } SyntaxData::Alias(s) => { sql.push_str("as "); push_identifier(&mut sql, s); diff --git a/sbroad-core/src/backend/sql/ir/tests/inner_join.rs b/sbroad-core/src/backend/sql/ir/tests/inner_join.rs index 2780d7986..43558fd3e 100644 --- a/sbroad-core/src/backend/sql/ir/tests/inner_join.rs +++ b/sbroad-core/src/backend/sql/ir/tests/inner_join.rs @@ -64,7 +64,7 @@ fn inner_join2_latest() { r#""hash_testing"."product_units","#, r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#, r#"INNER JOIN"#, - r#"(SELECT "history"."id" FROM "history" WHERE ("history"."id") = (?)) as "t""#, + r#"(SELECT * FROM "history" WHERE ("history"."id") = (?)) as "t""#, r#"ON ("hash_testing"."identification_number") = ("t"."id")"#, r#"WHERE ("hash_testing"."product_code") = (?)"#, ), @@ -89,7 +89,7 @@ fn inner_join2_oldest() { r#""hash_testing"."product_units","#, r#""hash_testing"."sys_op" FROM "hash_testing") as "hash_testing""#, r#"INNER JOIN"#, - r#"(SELECT "history"."id" FROM "history" WHERE ("history"."id") = (?)) as "t""#, + r#"(SELECT * FROM "history" WHERE ("history"."id") = (?)) as "t""#, r#"ON ("hash_testing"."identification_number") = ("t"."id")"#, r#"WHERE ("hash_testing"."product_code") = (?)"#, ), diff --git a/sbroad-core/src/backend/sql/ir/tests/projection.rs b/sbroad-core/src/backend/sql/ir/tests/projection.rs index ff49a8403..aa56503d5 100644 --- a/sbroad-core/src/backend/sql/ir/tests/projection.rs +++ b/sbroad-core/src/backend/sql/ir/tests/projection.rs @@ -47,10 +47,8 @@ fn projection2_latest() { WHERE "identification_number" = 1"#; let expected = PatternWithParams::new( format!( - "{} {} {} {} {}", - r#"SELECT "hash_testing"."identification_number","#, - r#""hash_testing"."product_code","#, - r#""hash_testing"."product_units", "hash_testing"."sys_op""#, + "{} {} {}", + r#"SELECT *"#, r#"FROM "hash_testing""#, r#"WHERE ("hash_testing"."identification_number") = (?)"# ), @@ -66,10 +64,8 @@ fn projection2_oldest() { WHERE "identification_number" = 1"#; let expected = PatternWithParams::new( format!( - "{} {} {} {} {}", - r#"SELECT "hash_testing"."identification_number","#, - r#""hash_testing"."product_code","#, - r#""hash_testing"."product_units", "hash_testing"."sys_op""#, + "{} {} {}", + r#"SELECT *"#, r#"FROM "hash_testing""#, r#"WHERE ("hash_testing"."identification_number") = (?)"# ), diff --git a/sbroad-core/src/backend/sql/tree.rs b/sbroad-core/src/backend/sql/tree.rs index 9ec30bd10..2cd8d34c3 100644 --- a/sbroad-core/src/backend/sql/tree.rs +++ b/sbroad-core/src/backend/sql/tree.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use smol_str::{format_smolstr, SmolStr}; +use std::collections::HashSet; use std::mem::take; use crate::errors::{Entity, SbroadError}; @@ -26,6 +27,8 @@ use sbroad_proc::otm_child_span; pub enum SyntaxData { /// "as \"alias_name\"" Alias(SmolStr), + /// "*" + Asterisk(Option<SmolStr>), /// "as alias_name" UnquotedAlias(SmolStr), /// "cast" @@ -116,6 +119,14 @@ pub struct SyntaxNode { } impl SyntaxNode { + fn new_asterisk(relation_name: Option<SmolStr>) -> Self { + SyntaxNode { + data: SyntaxData::Asterisk(relation_name), + left: None, + right: Vec::new(), + } + } + fn new_alias(name: SmolStr) -> Self { SyntaxNode { data: SyntaxData::Alias(name), @@ -1456,19 +1467,145 @@ impl<'p> SyntaxPlan<'p> { } } - let mut children = Vec::with_capacity(list.len() * 2 + 3); - // The nodes on the stack are in the reverse order. - children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_close())); - if let Some((first, others)) = list.split_first() { - for child_id in others.iter().rev() { - children.push(self.pop_from_stack(*child_id, id)); - children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_comma())); - } - children.push(self.pop_from_stack(*first, id)); + // Vec of row's sn children nodes. + let mut list_sn_ids = Vec::with_capacity(list.len()); + for list_id in list.iter().rev() { + list_sn_ids.push(self.pop_from_stack(*list_id, id)); } - children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_open())); // Need to reverse the order of the children back. - children.reverse(); + list_sn_ids.reverse(); + + // Set of relation names for which we've already generated asterisk (*). + // In case we see in output several references that we initially generated from + // an asterisk we want to generate that asterisk only once. + let mut already_handled_asterisk_sources = HashSet::new(); + let mut last_handled_asterisk_id: Option<usize> = None; + + // Children number + the same number of commas + parentheses. + let mut children = Vec::with_capacity(list.len() * 2 + 2); + children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_open())); + + enum NodeToAdd { + SnId(usize), + Asterisk(SyntaxNode), + Comma, + } + + let mut handle_reference = + |sn_id: usize, need_comma: bool, expr_node: &Expression| -> Vec<NodeToAdd> { + let mut non_reference_nodes = || -> Vec<NodeToAdd> { + let mut nodes_to_add = Vec::new(); + if last_handled_asterisk_id.is_some() { + nodes_to_add.push(NodeToAdd::Comma); + } + nodes_to_add.push(NodeToAdd::SnId(sn_id)); + if need_comma { + nodes_to_add.push(NodeToAdd::Comma); + } + last_handled_asterisk_id = None; + nodes_to_add + }; + + let mut nodes_to_add = Vec::new(); + if let Expression::Reference { + asterisk_source: + Some(ReferenceAsteriskSource { + relation_name, + asterisk_id, + }), + .. + } = expr_node + { + let mut need_comma = false; + let asterisk_id = *asterisk_id; + if let Some(last_handled_asterisk_id) = last_handled_asterisk_id { + if asterisk_id != last_handled_asterisk_id { + need_comma = true; + already_handled_asterisk_sources.clear(); + } + } + + let pair_to_check = if let Some(relation_name) = relation_name { + (Some(relation_name.clone()), asterisk_id) + } else { + (None, asterisk_id) + }; + + let asterisk_node_to_add = + if !already_handled_asterisk_sources.contains(&pair_to_check) { + already_handled_asterisk_sources.insert(pair_to_check); + let res = if relation_name.is_some() { + SyntaxNode::new_asterisk(relation_name.clone()) + } else { + SyntaxNode::new_asterisk(None) + }; + Some(res) + } else { + None + }; + + last_handled_asterisk_id = Some(asterisk_id); + if need_comma { + nodes_to_add.push(NodeToAdd::Comma); + } + if let Some(asterisk_node_to_add) = asterisk_node_to_add { + nodes_to_add.push(NodeToAdd::Asterisk(asterisk_node_to_add)); + } + } else { + return non_reference_nodes(); + } + nodes_to_add + }; + + let mut handle_single_list_sn_id = |sn_id: usize, + need_comma: bool| + -> Result<(), SbroadError> { + let sn_node = self.nodes.get_sn(sn_id); + let sn_plan_node = self.get_plan_node(&sn_node.data)?; + + let nodes_to_add = if let Some(Node::Expression(node_expr)) = sn_plan_node { + match node_expr { + Expression::Alias { child, .. } => { + let alias_child = self.plan.get_ir_plan().get_expression_node(*child)?; + handle_reference(sn_id, need_comma, alias_child) + } + _ => handle_reference(sn_id, need_comma, node_expr), + } + } 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 { + NodeToAdd::SnId(sn_id) => { + children.push(sn_id); + } + NodeToAdd::Asterisk(asterisk) => { + children.push(self.nodes.push_sn_non_plan(asterisk)) + } + NodeToAdd::Comma => { + children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_comma())) + } + } + } + + Ok(()) + }; + + if let Some((list_sn_id_last, list_sn_ids_other)) = list_sn_ids.split_last() { + for list_sn_id in list_sn_ids_other { + handle_single_list_sn_id(*list_sn_id, true).expect("Row child should be valid.") + } + handle_single_list_sn_id(*list_sn_id_last, false).expect("Row child should be valid.") + } + children.push(self.nodes.push_sn_non_plan(SyntaxNode::new_close())); let sn = SyntaxNode::new_pointer(id, None, children); self.nodes.push_sn_plan(sn); } diff --git a/sbroad-core/src/executor/tests.rs b/sbroad-core/src/executor/tests.rs index afe2234e8..9b407d9aa 100644 --- a/sbroad-core/src/executor/tests.rs +++ b/sbroad-core/src/executor/tests.rs @@ -74,7 +74,7 @@ fn shard_union_query() { LuaValue::String(String::from(PatternWithParams::new( format!( "{} {}{} {} {}{} {}", - r#"SELECT "t3"."id""#, + r#"SELECT *"#, r#"FROM ("#, r#"SELECT "test_space"."id" FROM "test_space" WHERE ("test_space"."sys_op") = (?)"#, r#"UNION ALL"#, @@ -252,7 +252,7 @@ fn union_linker_test() { LuaValue::String(String::from(PatternWithParams::new( format!( "{} {}{} {} {} {} {} {} {}{} {}", - r#"SELECT "t1"."id", "t1"."FIRST_NAME""#, + r#"SELECT *"#, r#"FROM ("#, r#"SELECT "test_space"."id", "test_space"."FIRST_NAME""#, r#"FROM "test_space""#, @@ -272,7 +272,7 @@ fn union_linker_test() { LuaValue::String(String::from(PatternWithParams::new( format!( "{} {}{} {} {} {} {} {} {}{} {}", - r#"SELECT "t1"."id", "t1"."FIRST_NAME""#, + r#"SELECT *"#, r#"FROM ("#, r#"SELECT "test_space"."id", "test_space"."FIRST_NAME""#, r#"FROM "test_space""#, @@ -350,10 +350,8 @@ WHERE "t3"."id" = 2 AND "t8"."identification_number" = 2"#; LuaValue::String(format!("Execute query on a bucket [{bucket2}]")), LuaValue::String(String::from(PatternWithParams::new( format!( - "{}, {}, {} {}{} {} {} {} {} {} {}{} {} {}{} {} {}", - r#"SELECT "t3"."id""#, - r#""t3"."FIRST_NAME""#, - r#""t8"."identification_number""#, + "{} {}{} {} {} {} {} {} {}{} {} {}{} {} {}", + r#"SELECT *"#, r#"FROM ("#, r#"SELECT "test_space"."id", "test_space"."FIRST_NAME""#, r#"FROM "test_space""#, @@ -678,7 +676,7 @@ on q."f" = "t1"."a""#; LuaValue::String(String::from(PatternWithParams::new( format!( "{} {} {} {}", - r#"SELECT "t1"."a", "t1"."b", "q"."f", "q"."b" FROM"#, + r#"SELECT * FROM"#, r#"(SELECT "t1"."a", "t1"."b" FROM "t1") as "t1""#, r#"INNER JOIN (SELECT "COL_1","COL_2" FROM "TMP_test_1136")"#, r#"as "q" ON ("q"."f") = ("t1"."a")"#, @@ -788,12 +786,8 @@ fn anonymous_col_index_test() { LuaValue::String(format!("Execute query on a bucket [{bucket3}]")), LuaValue::String(String::from(PatternWithParams::new( format!( - "{} {} {} {} {} {} {} {} {} {}", - "SELECT", - r#""test_space"."id","#, - r#""test_space"."sysFrom","#, - r#""test_space"."FIRST_NAME","#, - r#""test_space"."sys_op""#, + "{} {} {} {} {} {}", + "SELECT *", r#"FROM "test_space""#, r#"WHERE ("test_space"."id") in"#, r#"(SELECT "COL_1" FROM "TMP_test_1136")"#, @@ -807,13 +801,9 @@ fn anonymous_col_index_test() { LuaValue::String(format!("Execute query on a bucket [{bucket2}]")), LuaValue::String(String::from(PatternWithParams::new( format!( - "{} {} {} {} {} {} {} {} {} {}", + "{} {} {} {} {} {}", "SELECT", - r#""test_space"."id","#, - r#""test_space"."sysFrom","#, - r#""test_space"."FIRST_NAME","#, - r#""test_space"."sys_op""#, - r#"FROM "test_space""#, + r#"* FROM "test_space""#, r#"WHERE ("test_space"."id") in"#, r#"(SELECT "COL_1" FROM "TMP_test_1136")"#, r#"or ("test_space"."id") in"#, @@ -846,10 +836,8 @@ fn sharding_column1_test() { LuaValue::String(format!("Execute query on a bucket [{bucket}]")), LuaValue::String(String::from(PatternWithParams::new( format!( - "{} {} {}", - r#"SELECT "test_space"."id", "test_space"."sysFrom","#, - r#""test_space"."FIRST_NAME", "test_space"."sys_op""#, - r#"FROM "test_space" WHERE ("test_space"."id") = (?)"#, + "{} {}", + r#"SELECT *"#, r#"FROM "test_space" WHERE ("test_space"."id") = (?)"#, ), vec![Value::from(1_u64)], ))), @@ -877,9 +865,8 @@ fn sharding_column2_test() { LuaValue::String(format!("Execute query on a bucket [{bucket}]")), LuaValue::String(String::from(PatternWithParams::new( format!( - "{} {} {}", - r#"SELECT "test_space"."id", "test_space"."sysFrom","#, - r#""test_space"."FIRST_NAME", "test_space"."sys_op","#, + "{} {}", + r#"SELECT *,"#, r#""test_space"."bucket_id" FROM "test_space" WHERE ("test_space"."id") = (?)"#, ), vec![Value::from(1_u64)], diff --git a/sbroad-core/src/executor/tests/bucket_id.rs b/sbroad-core/src/executor/tests/bucket_id.rs index f494efe31..64f003f6d 100644 --- a/sbroad-core/src/executor/tests/bucket_id.rs +++ b/sbroad-core/src/executor/tests/bucket_id.rs @@ -24,7 +24,7 @@ fn bucket1_test() { expected.rows.push(vec![ LuaValue::String("Execute query on all buckets".to_string()), LuaValue::String(String::from(PatternWithParams::new( - r#"SELECT "t1"."a", "t1"."b", "t1"."bucket_id" FROM "t1""#.to_string(), + r#"SELECT *, "t1"."bucket_id" FROM "t1""#.to_string(), vec![], ))), ]); @@ -83,7 +83,7 @@ fn bucket3_test() { expected.rows.push(vec![ LuaValue::String("Execute query on all buckets".to_string()), LuaValue::String(String::from(PatternWithParams::new( - r#"SELECT "t1"."a", "t1"."b", "func" (?) as "col_1" FROM "t1""#.to_string(), + r#"SELECT *, "func" (?) as "col_1" FROM "t1""#.to_string(), vec![Value::from("111".to_string())], ))), ]); diff --git a/sbroad-core/src/executor/tests/empty_motion.rs b/sbroad-core/src/executor/tests/empty_motion.rs index 913412f9b..bbb95c6c7 100644 --- a/sbroad-core/src/executor/tests/empty_motion.rs +++ b/sbroad-core/src/executor/tests/empty_motion.rs @@ -64,7 +64,7 @@ fn empty_motion1_test() { LuaValue::String(String::from(PatternWithParams::new( format!( "{} {} {} {} {} {} {} {} {} {} {} {} {} {}", - r#"SELECT "Q"."a", "Q"."b" FROM"#, + r#"SELECT * FROM"#, r#"(SELECT "t"."a", "t"."b" FROM"#, r#"(SELECT "t"."a", "t"."b", "t"."c", "t"."d" FROM "t") as "t""#, r#"INNER JOIN"#, diff --git a/sbroad-core/src/executor/tests/exec_plan.rs b/sbroad-core/src/executor/tests/exec_plan.rs index a13c00713..b299551cf 100644 --- a/sbroad-core/src/executor/tests/exec_plan.rs +++ b/sbroad-core/src/executor/tests/exec_plan.rs @@ -387,7 +387,7 @@ fn exec_plan_subquery_under_motion_without_alias() { assert_eq!( sql, PatternWithParams::new( - r#"SELECT "tid", "COL_1" as "sid" FROM (SELECT "test_space"."id" as "tid" FROM "test_space") INNER JOIN (SELECT "COL_1" FROM "TMP_test_0136") ON ?"#.to_string(), + r#"SELECT * FROM (SELECT "test_space"."id" as "tid" FROM "test_space") INNER JOIN (SELECT "COL_1" FROM "TMP_test_0136") ON ?"#.to_string(), vec![Value::Boolean(true)] )); } @@ -428,7 +428,7 @@ fn exec_plan_subquery_under_motion_with_alias() { assert_eq!( sql, PatternWithParams::new( - r#"SELECT "tid", "hti"."COL_1" as "sid" FROM (SELECT "test_space"."id" as "tid" FROM "test_space") INNER JOIN (SELECT "COL_1" FROM "TMP_test_0136") as "hti" ON ?"#.to_string(), + r#"SELECT * FROM (SELECT "test_space"."id" as "tid" FROM "test_space") INNER JOIN (SELECT "COL_1" FROM "TMP_test_0136") as "hti" ON ?"#.to_string(), vec![Value::Boolean(true)] )); } @@ -749,13 +749,7 @@ fn global_table_scan() { assert_eq!( sql, - PatternWithParams::new( - format!( - "{}", - r#"SELECT "global_t"."a", "global_t"."b" FROM "global_t""#, - ), - vec![] - ) + PatternWithParams::new(format!("{}", r#"SELECT * FROM "global_t""#,), vec![]) ); } @@ -1035,13 +1029,13 @@ fn global_union_all4() { let expected = vec![ ReplicasetDispatchInfo { rs_id: 0, - pattern: r#" select cast(null as integer) where false UNION ALL SELECT "a" FROM (select cast(null as integer) where false UNION ALL SELECT "t2"."f" FROM "t2")"#.to_string(), + pattern: r#" select cast(null as integer) where false UNION ALL SELECT * FROM (select cast(null as integer) where false UNION ALL SELECT "t2"."f" FROM "t2")"#.to_string(), params: vec![], vtables_map: HashMap::new(), }, ReplicasetDispatchInfo { rs_id: 1, - pattern: r#"SELECT "global_t"."b" FROM "global_t" UNION ALL SELECT "a" FROM (SELECT "global_t"."a" FROM "global_t" UNION ALL SELECT "t2"."f" FROM "t2")"#.to_string(), + pattern: r#"SELECT "global_t"."b" FROM "global_t" UNION ALL SELECT * FROM (SELECT "global_t"."a" FROM "global_t" UNION ALL SELECT "t2"."f" FROM "t2")"#.to_string(), params: vec![], vtables_map: HashMap::new(), }, @@ -1290,7 +1284,7 @@ fn exec_plan_order_by_with_join() { assert_eq!( sql, PatternWithParams::new( - r#"SELECT "f"."a", "s"."COL_1" as "a" FROM (SELECT "t"."a" FROM "t") as "f" INNER JOIN (SELECT "COL_1" FROM "TMP_test_28") as "s" ON ?"#.to_string(), + r#"SELECT * FROM (SELECT "t"."a" FROM "t") as "f" INNER JOIN (SELECT "COL_1" FROM "TMP_test_28") as "s" ON ?"#.to_string(), vec![Value::Boolean(true)] ) ); diff --git a/sbroad-core/src/frontend/sql.rs b/sbroad-core/src/frontend/sql.rs index 5782229fd..7a552669b 100644 --- a/sbroad-core/src/frontend/sql.rs +++ b/sbroad-core/src/frontend/sql.rs @@ -33,7 +33,7 @@ use crate::ir::expression::{ ColumnPositionMap, ColumnWithScan, ColumnsRetrievalSpec, ExpressionId, FunctionFeature, Position, TrimKind, }; -use crate::ir::node::expression::{Expression, MutExpression}; +use crate::ir::node::expression::{Expression, MutExpression, ReferenceAsteriskSource}; use crate::ir::node::relational::Relational; use crate::ir::node::{ AlterSystem, AlterUser, BoolExpr, Constant, CountAsterisk, CreateIndex, CreateProc, CreateRole, @@ -2268,7 +2268,7 @@ where let col_type = plan .get_expression_node(*child_alias_id)? .calculate_type(plan)?; - let ref_id = plan.nodes.add_ref(None, Some(vec![0]), col_position, col_type); + let ref_id = plan.nodes.add_ref(None, Some(vec![0]), col_position, col_type, None); (ref_id, false) }; worker.reference_to_name_map.insert(ref_id, (col_name, is_row)); @@ -3099,6 +3099,10 @@ impl AbstractSyntaxTree { let mut proj_columns: Vec<NodeId> = Vec::with_capacity(ast_columns_ids.len()); let mut unnamed_col_pos = 0; + // Unique identifier for each "*" met under projection. Uniqueness is local + // for each projection. Used to distinguish the source of asterisk projections + // like `select *, * from t`, where there are several of them. + let mut asterisk_id = 0; for ast_column_id in ast_columns_ids { let ast_column = self.nodes.get_node(*ast_column_id)?; match ast_column.rule { @@ -3152,15 +3156,25 @@ impl AbstractSyntaxTree { plan_rel_child_id, filtered_col_ids, false, + Some(ReferenceAsteriskSource::new( + Some(table_name), + asterisk_id, + )), )? } else { - plan.add_row_for_output(plan_rel_child_id, &[], false)? + plan.add_row_for_output( + plan_rel_child_id, + &[], + false, + Some(ReferenceAsteriskSource::new(None, asterisk_id)), + )? }; let row_list = plan.get_row_list(plan_asterisk_id)?; for row_id in row_list { proj_columns.push(*row_id); } + asterisk_id += 1; } _ => { return Err(SbroadError::Invalid( @@ -3404,6 +3418,7 @@ impl AbstractSyntaxTree { &NewColumnsSource::Other { child: proj_child_id, columns_spec: Some(ColumnsRetrievalSpec::Names(pk_columns)), + asterisk_source: None, }, false, false, diff --git a/sbroad-core/src/frontend/sql/ir.rs b/sbroad-core/src/frontend/sql/ir.rs index feb53e417..6b8a5bfeb 100644 --- a/sbroad-core/src/frontend/sql/ir.rs +++ b/sbroad-core/src/frontend/sql/ir.rs @@ -467,6 +467,7 @@ impl SubtreeCloner { targets: _, position: _, col_type: _, + asterisk_source: _, }) | ExprOwned::CountAsterisk { .. } => {} ExprOwned::Alias(Alias { diff --git a/sbroad-core/src/ir/aggregates.rs b/sbroad-core/src/ir/aggregates.rs index d06ba2240..8b447a6b9 100644 --- a/sbroad-core/src/ir/aggregates.rs +++ b/sbroad-core/src/ir/aggregates.rs @@ -316,6 +316,7 @@ impl SimpleAggregate { targets: Some(vec![0]), position, col_type: fun_type.clone(), + asterisk_source: None, }; let ref_id = plan.nodes.push(ref_node.into()); let children = match self.kind { diff --git a/sbroad-core/src/ir/expression.rs b/sbroad-core/src/ir/expression.rs index 9c3eb7579..5700fcdba 100644 --- a/sbroad-core/src/ir/expression.rs +++ b/sbroad-core/src/ir/expression.rs @@ -32,6 +32,25 @@ pub mod types; pub(crate) type ExpressionId = NodeId; +/// Helper structure for cases of references generated from asterisk. +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Hash)] +pub struct ReferenceAsteriskSource { + /// None -> generated from simple asterisk: `select * from t` + /// Some(relation_name) -> generated from table asterisk: `select t.* from t` + pub relation_name: Option<SmolStr>, + /// Unique asterisk id local for single Projection + pub asterisk_id: usize, +} + +impl ReferenceAsteriskSource { + pub fn new(relation_name: Option<SmolStr>, asterisk_id: usize) -> Self { + Self { + relation_name, + asterisk_id, + } + } +} + #[derive(Clone, Debug, Hash, Deserialize, PartialEq, Eq, Serialize)] pub enum FunctionFeature { /// Current function is an aggregate function and is marked as DISTINCT. @@ -139,12 +158,14 @@ impl Nodes { targets: Option<Vec<usize>>, position: usize, col_type: Type, + asterisk_source: Option<ReferenceAsteriskSource>, ) -> NodeId { let r = Reference { parent, targets, position, col_type, + asterisk_source, }; self.push(r.into()) } @@ -549,6 +570,7 @@ impl<'plan> Comparator<'plan> { position, targets, col_type, + asterisk_source: is_asterisk, }) => match self.policy { ReferencePolicy::ByAliases => { self.plan @@ -561,6 +583,7 @@ impl<'plan> Comparator<'plan> { position.hash(state); targets.hash(state); col_type.hash(state); + is_asterisk.hash(state); } }, Expression::Row(Row { list, .. }) => { @@ -574,7 +597,7 @@ impl<'plan> Comparator<'plan> { func_type, feature, is_system: is_aggr, - }) => { + } => { feature.hash(state); func_type.hash(state); name.hash(state); @@ -815,6 +838,8 @@ pub enum NewColumnsSource<'targets> { Other { child: NodeId, columns_spec: Option<ColumnsRetrievalSpec<'targets>>, + /// Indicates whether requested output is coming from asterisk. + asterisk_source: Option<ReferenceAsteriskSource>, }, } @@ -899,6 +924,15 @@ impl<'source> NewColumnsSource<'source> { } } + fn get_asterisk_source(&self) -> Option<ReferenceAsteriskSource> { + match self { + NewColumnsSource::Other { + asterisk_source, .. + } => asterisk_source.clone(), + _ => None, + } + } + fn targets(&self) -> Vec<usize> { match self { NewColumnsSource::Join { targets, .. } => match targets { @@ -1027,9 +1061,13 @@ impl Plan { let mut result_row_list: Vec<NodeId> = Vec::with_capacity(filtered_children_row_list.len()); for (pos, alias_node_id, new_targets) in filtered_children_row_list { let alias_expr = self.get_expression_node(alias_node_id)?; + let asterisk_source = source.get_asterisk_source(); let alias_name = SmolStr::from(alias_expr.get_alias_name()?); let col_type = alias_expr.calculate_type(self)?; - let r_id = self.nodes.add_ref(None, Some(new_targets), pos, col_type); + + let r_id = self + .nodes + .add_ref(None, Some(new_targets), pos, col_type, asterisk_source); if need_aliases { let a_id = self.nodes.add_alias(&alias_name, r_id)?; result_row_list.push(a_id); @@ -1052,11 +1090,13 @@ impl Plan { rel_node: NodeId, indices: Vec<usize>, need_sharding_column: bool, + asterisk_source: Option<ReferenceAsteriskSource>, ) -> Result<NodeId, SbroadError> { let list = self.new_columns( &NewColumnsSource::Other { child: rel_node, columns_spec: Some(ColumnsRetrievalSpec::Indices(indices)), + asterisk_source, }, true, need_sharding_column, @@ -1076,6 +1116,7 @@ impl Plan { rel_node: NodeId, col_names: &[&str], need_sharding_column: bool, + asterisk_source: Option<ReferenceAsteriskSource>, ) -> Result<NodeId, SbroadError> { let specific_columns = if col_names.is_empty() { None @@ -1091,6 +1132,7 @@ impl Plan { &NewColumnsSource::Other { child: rel_node, columns_spec: specific_columns, + asterisk_source, }, true, need_sharding_column, @@ -1166,6 +1208,7 @@ impl Plan { &NewColumnsSource::Other { child, columns_spec: specific_columns, + asterisk_source: None, }, false, true, @@ -1202,7 +1245,7 @@ impl Plan { let alias_type = self.get_expression_node(alias_id)?.calculate_type(self)?; let ref_id = self .nodes - .add_ref(parent, Some(vec![target]), pos, alias_type); + .add_ref(parent, Some(vec![target]), pos, alias_type, None); new_refs.push(ref_id); } let row_id = self.nodes.add_row(new_refs, None); diff --git a/sbroad-core/src/ir/helpers.rs b/sbroad-core/src/ir/helpers.rs index 91a263992..33557db97 100644 --- a/sbroad-core/src/ir/helpers.rs +++ b/sbroad-core/src/ir/helpers.rs @@ -142,8 +142,9 @@ impl Plan { position, parent, col_type, + .. }) => { - let alias_name = self.get_alias_from_reference_node(&expr).unwrap(); + let alias_name = self.get_alias_from_reference_node(expr).unwrap(); writeln!(buf, "Reference")?; writeln_with_tabulation( diff --git a/sbroad-core/src/ir/helpers/tests.rs b/sbroad-core/src/ir/helpers/tests.rs index b02b703a8..cbb7b7291 100644 --- a/sbroad-core/src/ir/helpers/tests.rs +++ b/sbroad-core/src/ir/helpers/tests.rs @@ -20,11 +20,11 @@ fn simple_select() { Output_id: 564 [id: 564] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 032] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer })] - [id: 132] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 1, col_type: String })] - [id: 232] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean })] - [id: 332] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned })] - [id: 432] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned })] + [id: 032] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer, asterisk_source: None })] + [id: 132] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 1, col_type: String, asterisk_source: None })] + [id: 232] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean, asterisk_source: None })] + [id: 332] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned, asterisk_source: None })] + [id: 432] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 964] relation: Projection @@ -33,7 +33,7 @@ fn simple_select() { Output_id: 864 [id: 864] expression: Row [distribution = Some(Any)] List: - [id: 532] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 9, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String })] + [id: 532] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 9, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String, asterisk_source: None })] --------------------------------------------- "#); @@ -59,11 +59,11 @@ fn simple_join() { Output_id: 564 [id: 564] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 032] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 0, col_type: Unsigned })] - [id: 132] expression: Alias [name = sysFrom, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 1, col_type: Unsigned })] - [id: 232] expression: Alias [name = FIRST_NAME, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 2, col_type: String })] - [id: 332] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned })] - [id: 432] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned })] + [id: 032] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 0, col_type: Unsigned, asterisk_source: None })] + [id: 132] expression: Alias [name = sysFrom, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 1, col_type: Unsigned, asterisk_source: None })] + [id: 232] expression: Alias [name = FIRST_NAME, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 2, col_type: String, asterisk_source: None })] + [id: 332] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned, asterisk_source: None })] + [id: 432] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 964] relation: Projection @@ -72,7 +72,7 @@ fn simple_join() { Output_id: 864 [id: 864] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 532] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 9, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned })] + [id: 532] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 9, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 1264] relation: ScanSubQuery @@ -82,7 +82,7 @@ fn simple_join() { Output_id: 1164 [id: 1164] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 632] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 12, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned })] + [id: 632] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 12, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 1964] relation: ScanRelation @@ -91,11 +91,11 @@ fn simple_join() { Output_id: 1864 [id: 1864] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 732] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer })] - [id: 832] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 1, col_type: String })] - [id: 932] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean })] - [id: 1032] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned })] - [id: 1132] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned })] + [id: 732] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer, asterisk_source: None })] + [id: 832] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 1, col_type: String, asterisk_source: None })] + [id: 932] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean, asterisk_source: None })] + [id: 1032] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned, asterisk_source: None })] + [id: 1132] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 2264] relation: Projection @@ -104,7 +104,7 @@ fn simple_join() { Output_id: 2164 [id: 2164] expression: Row [distribution = Some(Any)] List: - [id: 1232] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 22, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer })] + [id: 1232] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 22, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 2564] relation: ScanSubQuery @@ -114,7 +114,7 @@ fn simple_join() { Output_id: 2464 [id: 2464] expression: Row [distribution = Some(Any)] List: - [id: 1332] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 25, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer })] + [id: 1332] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 25, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 0136] relation: Motion [policy = Segment(MotionKey { targets: [Reference(0)] }), alias = t2] @@ -123,7 +123,7 @@ fn simple_join() { Output_id: 4064 [id: 4064] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 1932] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 0, arena_type: Arena136 }), targets: Some([0]), position: 0, col_type: Integer })] + [id: 1932] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 0, arena_type: Arena136 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 3364] relation: InnerJoin @@ -153,8 +153,8 @@ fn simple_join() { Output_id: 3264 [id: 3264] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [1] }, Key { positions: [0] }}) })] List: - [id: 1532] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 33, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned })] - [id: 1632] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 33, arena_type: Arena64 }), targets: Some([1]), position: 0, col_type: Integer })] + [id: 1532] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 33, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned, asterisk_source: None })] + [id: 1632] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 33, arena_type: Arena64 }), targets: Some([1]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 3664] relation: Projection @@ -163,7 +163,7 @@ fn simple_join() { Output_id: 3564 [id: 3564] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 1732] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 36, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned })] + [id: 1732] expression: Alias [name = id, child = Reference(Reference { parent: Some(NodeId { offset: 36, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- "#); @@ -197,11 +197,11 @@ fn simple_join_subtree() { Output_id: 1864 [id: 1864] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 732] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer })] - [id: 832] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 1, col_type: String })] - [id: 932] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean })] - [id: 1032] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned })] - [id: 1132] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned })] + [id: 732] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer, asterisk_source: None })] + [id: 832] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 1, col_type: String, asterisk_source: None })] + [id: 932] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean, asterisk_source: None })] + [id: 1032] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned, asterisk_source: None })] + [id: 1132] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 19, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 2264] relation: Projection @@ -210,7 +210,7 @@ fn simple_join_subtree() { Output_id: 2164 [id: 2164] expression: Row [distribution = Some(Any)] List: - [id: 1232] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 22, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer })] + [id: 1232] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 22, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 2564] relation: ScanSubQuery @@ -220,7 +220,7 @@ fn simple_join_subtree() { Output_id: 2464 [id: 2464] expression: Row [distribution = Some(Any)] List: - [id: 1332] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 25, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer })] + [id: 1332] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 25, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 0136] relation: Motion [policy = Segment(MotionKey { targets: [Reference(0)] }), alias = t2] @@ -229,7 +229,7 @@ fn simple_join_subtree() { Output_id: 4064 [id: 4064] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 1932] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 0, arena_type: Arena136 }), targets: Some([0]), position: 0, col_type: Integer })] + [id: 1932] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 0, arena_type: Arena136 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] --------------------------------------------- "# ); @@ -252,26 +252,26 @@ fn simple_aggregation_with_group_by() { Output_id: 564 [id: 564] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 032] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer })] - [id: 132] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 1, col_type: String })] - [id: 232] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean })] - [id: 332] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned })] - [id: 432] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned })] + [id: 032] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 0, col_type: Integer, asterisk_source: None })] + [id: 132] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 1, col_type: String, asterisk_source: None })] + [id: 232] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 2, col_type: Boolean, asterisk_source: None })] + [id: 332] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 3, col_type: Unsigned, asterisk_source: None })] + [id: 432] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 6, arena_type: Arena64 }), targets: None, position: 4, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 1464] relation: GroupBy [is_final = false] Gr_cols: - Gr_col: Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String }) + Gr_col: Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String, asterisk_source: None }) Children: Child_id = 664 Output_id: 1364 [id: 1364] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0, 1] }}) })] List: - [id: 532] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer })] - [id: 632] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String })] - [id: 732] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 2, col_type: Boolean })] - [id: 832] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 3, col_type: Unsigned })] - [id: 932] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 4, col_type: Unsigned })] + [id: 532] expression: Alias [name = identification_number, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: Integer, asterisk_source: None })] + [id: 632] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String, asterisk_source: None })] + [id: 732] expression: Alias [name = product_units, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 2, col_type: Boolean, asterisk_source: None })] + [id: 832] expression: Alias [name = sys_op, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 3, col_type: Unsigned, asterisk_source: None })] + [id: 932] expression: Alias [name = bucket_id, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 4, col_type: Unsigned, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 1964] relation: Projection @@ -280,7 +280,7 @@ fn simple_aggregation_with_group_by() { Output_id: 1864 [id: 1864] expression: Row [distribution = Some(Any)] List: - [id: 1132] expression: Alias [name = column_764, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String })] + [id: 1132] expression: Alias [name = column_764, child = Reference(Reference { parent: Some(NodeId { offset: 14, arena_type: Arena64 }), targets: Some([0]), position: 1, col_type: String, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 41] relation: Motion [policy = Segment(MotionKey { targets: [Reference(0)] }), alias = None] @@ -289,18 +289,18 @@ fn simple_aggregation_with_group_by() { Output_id: 40 [id: 40] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 39] expression: Alias [name = column_12, child = Reference { parent: Some(41), targets: Some([0]), position: 0, col_type: String }] + [id: 39] expression: Alias [name = column_12, child = Reference { parent: Some(41), targets: Some([0]), position: 0, col_type: String, asterisk_source: None }] --------------------------------------------- --------------------------------------------- [id: 2664] relation: GroupBy [is_final = true] Gr_cols: - Gr_col: Reference(Reference { parent: Some(NodeId { offset: 26, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: String }) + Gr_col: Reference(Reference { parent: Some(NodeId { offset: 26, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: String, asterisk_source: None }) Children: Child_id = 0136 Output_id: 2564 [id: 2564] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 1332] expression: Alias [name = column_764, child = Reference(Reference { parent: Some(NodeId { offset: 26, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: String })] + [id: 1332] expression: Alias [name = column_764, child = Reference(Reference { parent: Some(NodeId { offset: 26, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: String, asterisk_source: None })] --------------------------------------------- --------------------------------------------- [id: 1764] relation: Projection @@ -309,7 +309,7 @@ fn simple_aggregation_with_group_by() { Output_id: 1664 [id: 1664] expression: Row [distribution = Some(Segment { keys: KeySet({Key { positions: [0] }}) })] List: - [id: 1032] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 17, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: String })] + [id: 1032] expression: Alias [name = product_code, child = Reference(Reference { parent: Some(NodeId { offset: 17, arena_type: Arena64 }), targets: Some([0]), position: 0, col_type: String, asterisk_source: None })] --------------------------------------------- "#); diff --git a/sbroad-core/src/ir/operator.rs b/sbroad-core/src/ir/operator.rs index 6afb09444..3e7e23d4f 100644 --- a/sbroad-core/src/ir/operator.rs +++ b/sbroad-core/src/ir/operator.rs @@ -337,7 +337,7 @@ impl Plan { /// # Errors /// - child id pointes to non-existing or non-relational node. pub fn add_delete(&mut self, table: SmolStr, child_id: NodeId) -> Result<NodeId, SbroadError> { - let output = self.add_row_for_output(child_id, &[], true)?; + let output = self.add_row_for_output(child_id, &[], true, None)?; let delete = Delete { relation: table, children: vec![child_id], @@ -479,6 +479,7 @@ impl Plan { targets: Some(vec![0]), position: output_pos, col_type, + asterisk_source: None, }; let id = plan.nodes.push(node.into()); Ok(id) @@ -634,7 +635,7 @@ impl Plan { }; let proj_id = self.add_relational(proj_node.into())?; self.replace_parent_in_subtree(proj_output, None, Some(proj_id))?; - let upd_output = self.add_row_for_output(proj_id, &[], false)?; + let upd_output = self.add_row_for_output(proj_id, &[], false, None)?; let update_node = Update { relation: relation.to_smolstr(), pk_positions: primary_key_positions, @@ -718,7 +719,9 @@ 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.clone()); + let r_id = self + .nodes + .add_ref(None, None, pos, col.r#type.clone(), None); let col_alias_id = self.nodes.add_alias(&col.name, r_id)?; refs.push(col_alias_id); } @@ -754,7 +757,7 @@ impl Plan { if let Some(rel) = self.relations.get(table) { let mut refs: Vec<NodeId> = Vec::with_capacity(rel.columns.len()); for (pos, col) in rel.columns.iter().enumerate() { - let r_id = nodes.add_ref(None, None, pos, col.r#type.clone()); + let r_id = nodes.add_ref(None, None, pos, col.r#type.clone(), None); let col_alias_id = nodes.add_alias(&col.name, r_id)?; refs.push(col_alias_id); } @@ -920,7 +923,7 @@ impl Plan { _ => None, }; - let output = self.add_row_for_output(child_id, &[], true)?; + let output = self.add_row_for_output(child_id, &[], true, None)?; match policy { MotionPolicy::None => { return Err(SbroadError::Invalid( @@ -977,7 +980,7 @@ impl Plan { is_distinct: bool, needs_shard_col: bool, ) -> Result<NodeId, SbroadError> { - let output = self.add_row_for_output(child, col_names, needs_shard_col)?; + let output = self.add_row_for_output(child, col_names, needs_shard_col, None)?; let proj = Projection { children: vec![child], output, @@ -1039,7 +1042,7 @@ impl Plan { )); } - let output = self.add_row_for_output(first_child, &[], true)?; + let output = self.add_row_for_output(first_child, &[], true, None)?; let select = Selection { children: children.into(), filter, @@ -1087,7 +1090,7 @@ impl Plan { } } - let output = self.add_row_for_output(first_child, &[], true)?; + let output = self.add_row_for_output(first_child, &[], true, None)?; let having = Having { children: children.into(), filter, @@ -1113,7 +1116,7 @@ impl Plan { child: NodeId, order_by_elements: Vec<OrderByElement>, ) -> Result<NodeId, SbroadError> { - let output = self.add_row_for_output(child, &[], true)?; + let output = self.add_row_for_output(child, &[], true, None)?; let order_by = OrderBy { child, output, @@ -1147,7 +1150,7 @@ impl Plan { ) -> Result<NodeId, SbroadError> { let name: Option<SmolStr> = alias.map(SmolStr::from); - let output = self.add_row_for_output(child, &[], true)?; + let output = self.add_row_for_output(child, &[], true, None)?; let sq = ScanSubQuery { alias: name, children: vec![child], @@ -1219,7 +1222,7 @@ impl Plan { } let output = self - .add_row_for_output(child_id, &[], true) + .add_row_for_output(child_id, &[], true, None) .expect("output row for CTE"); let cte = ScanCte { alias, @@ -1285,7 +1288,7 @@ impl Plan { /// # Errors /// - Row node is not of a row type pub fn add_limit(&mut self, select: NodeId, limit: u64) -> Result<NodeId, SbroadError> { - let output = self.add_row_for_output(select, &[], true)?; + let output = self.add_row_for_output(select, &[], true, None)?; let limit = Limit { output, limit, @@ -1395,6 +1398,7 @@ impl Plan { Some((0..value_rows.len()).collect::<Vec<usize>>()), pos, col_type, + None, ); let alias_id = self.nodes.add_alias(name, ref_id)?; aliases.push(alias_id); diff --git a/sbroad-core/src/ir/transformation/equality_propagation.rs b/sbroad-core/src/ir/transformation/equality_propagation.rs index b4917ad65..ea6aa2bba 100644 --- a/sbroad-core/src/ir/transformation/equality_propagation.rs +++ b/sbroad-core/src/ir/transformation/equality_propagation.rs @@ -91,7 +91,7 @@ use crate::errors::{Entity, SbroadError}; use crate::ir::helpers::RepeatableState; -use crate::ir::node::expression::Expression; +use crate::ir::node::expression::{Expression, ReferenceAsteriskSource}; use crate::ir::node::{Constant, NodeId, Reference, Row}; use crate::ir::operator::Bool; use crate::ir::relation::Type; @@ -112,6 +112,7 @@ struct EqClassRef { position: usize, parent: Option<NodeId>, col_type: Type, + asterisk_source: Option<ReferenceAsteriskSource>, } impl EqClassRef { @@ -121,6 +122,7 @@ impl EqClassRef { position: expr_pos, parent: expr_prt, col_type: expr_type, + asterisk_source: expr_asterisk_source, }) = expr { return Ok(EqClassRef { @@ -128,6 +130,7 @@ impl EqClassRef { position: *expr_pos, parent: *expr_prt, col_type: expr_type.clone(), + asterisk_source: expr_asterisk_source.clone(), }); } Err(SbroadError::Invalid(Entity::Expression, None)) @@ -139,6 +142,7 @@ impl EqClassRef { self.targets.clone(), self.position, self.col_type.clone(), + self.asterisk_source.clone(), ); plan.nodes.add_row(vec![id], None) } diff --git a/sbroad-core/src/ir/transformation/equality_propagation/tests.rs b/sbroad-core/src/ir/transformation/equality_propagation/tests.rs index 696ce4b30..f8c6cf6f5 100644 --- a/sbroad-core/src/ir/transformation/equality_propagation/tests.rs +++ b/sbroad-core/src/ir/transformation/equality_propagation/tests.rs @@ -107,8 +107,8 @@ fn equality_propagation5() { r#"SELECT "t"."a" FROM "t""#, r#"WHERE ("t"."d") = (?) and ("t"."c") = (?)"#, r#"and ("t"."a") = (?) and ("t"."b") = (?)"#, - r#"and ("t"."b") = ("t"."c") and ("t"."c") = ("t"."d")"#, - r#"and ("t"."d") = ("t"."a")"#, + r#"and ("t"."b") = ("t"."c") and ("t"."c") = ("t"."a")"#, + r#"and ("t"."a") = ("t"."d")"#, ), vec![ Value::from(1_u64), diff --git a/sbroad-core/src/ir/transformation/not_push_down/tests.rs b/sbroad-core/src/ir/transformation/not_push_down/tests.rs index 43db64cd2..a892ce5d9 100644 --- a/sbroad-core/src/ir/transformation/not_push_down/tests.rs +++ b/sbroad-core/src/ir/transformation/not_push_down/tests.rs @@ -12,7 +12,7 @@ fn push_down_not(plan: &mut Plan) { fn not_true() { let input = r#"SELECT * FROM (values (1)) where not true"#; let expected = PatternWithParams::new( - r#"SELECT "COLUMN_1" FROM (VALUES (?)) WHERE (?)"#.to_string(), + r#"SELECT * FROM (VALUES (?)) WHERE (?)"#.to_string(), vec![Value::Unsigned(1), Value::from(false)], ); let actual = check_transformation(input, vec![], &push_down_not); @@ -24,7 +24,7 @@ fn not_true() { fn not_double() { let input = r#"SELECT * FROM (values (1)) where not not true"#; let expected = PatternWithParams::new( - r#"SELECT "COLUMN_1" FROM (VALUES (?)) WHERE (?)"#.to_string(), + r#"SELECT * FROM (VALUES (?)) WHERE (?)"#.to_string(), vec![Value::Unsigned(1), Value::from(true)], ); let actual = check_transformation(input, vec![], &push_down_not); @@ -36,7 +36,7 @@ fn not_double() { fn not_null() { let input = r#"SELECT * FROM (values (1)) where not null"#; let expected = PatternWithParams::new( - r#"SELECT "COLUMN_1" FROM (VALUES (?)) WHERE (?)"#.to_string(), + r#"SELECT * FROM (VALUES (?)) WHERE (?)"#.to_string(), vec![Value::Unsigned(1), Value::Null], ); let actual = check_transformation(input, vec![], &push_down_not); @@ -48,7 +48,7 @@ fn not_null() { fn not_and() { let input = r#"SELECT * FROM (values (1)) where not (true and false)"#; let expected = PatternWithParams::new( - r#"SELECT "COLUMN_1" FROM (VALUES (?)) WHERE ((?) or (?))"#.to_string(), + r#"SELECT * FROM (VALUES (?)) WHERE ((?) or (?))"#.to_string(), vec![Value::Unsigned(1), Value::from(false), Value::from(true)], ); let actual = check_transformation(input, vec![], &push_down_not); @@ -60,7 +60,7 @@ fn not_and() { fn not_or() { let input = r#"SELECT * FROM (values (1)) where not (false or true)"#; let expected = PatternWithParams::new( - r#"SELECT "COLUMN_1" FROM (VALUES (?)) WHERE ((?) and (?))"#.to_string(), + r#"SELECT * FROM (VALUES (?)) WHERE ((?) and (?))"#.to_string(), vec![Value::Unsigned(1), Value::from(true), Value::from(false)], ); let actual = check_transformation(input, vec![], &push_down_not); diff --git a/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs b/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs index 82541cf4f..bc532cfe0 100644 --- a/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs +++ b/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs @@ -300,12 +300,14 @@ impl EqualityCols { position: pos_left, parent: parent_left, col_type: col_type_left, + asterisk_source: asterisk_source_left, }), - Expression::Reference(Reference { + Expression::Reference { targets: targets_right, position: pos_right, parent: parent_right, col_type: col_type_right, + asterisk_source: asterisk_source_right, }), ) => { // TODO: compare types only if the runtime requires it. @@ -315,6 +317,7 @@ impl EqualityCols { if targets_left != targets_right && parent_left == parent_right && col_type_left == col_type_right + && asterisk_source_left == asterisk_source_right { let left_referred_child_id = *plan.get_relational_from_reference_node(*left_id)?; diff --git a/sbroad-core/src/ir/transformation/redistribution/groupby.rs b/sbroad-core/src/ir/transformation/redistribution/groupby.rs index 941c691fb..1d7a5ec60 100644 --- a/sbroad-core/src/ir/transformation/redistribution/groupby.rs +++ b/sbroad-core/src/ir/transformation/redistribution/groupby.rs @@ -696,7 +696,7 @@ impl Plan { is_final: bool, expr_parent: Option<NodeId>, ) -> Result<NodeId, SbroadError> { - let final_output = self.add_row_for_output(child_id, &[], true)?; + let final_output = self.add_row_for_output(child_id, &[], true, None)?; let groupby = GroupBy { children: [child_id].to_vec(), gr_cols: grouping_exprs.to_vec(), @@ -1410,6 +1410,7 @@ impl Plan { parent: None, targets: Some(vec![0]), col_type, + asterisk_source: None, }; nodes.push(new_col); } @@ -1417,7 +1418,7 @@ impl Plan { let new_col_id = self.nodes.push(node.into()); gr_cols.push(new_col_id); } - let output = self.add_row_for_output(child_id, &[], true)?; + let output = self.add_row_for_output(child_id, &[], true, None)?; let final_id = self.nodes.next_id(ArenaType::Arena64); for col in &gr_cols { self.replace_parent_in_subtree(*col, None, Some(final_id))?; @@ -1503,6 +1504,7 @@ impl Plan { targets: Some(vec![0]), position, col_type, + asterisk_source: None, }; nodes.push((parent, expr_id, gr_expr_id, new_ref)); } @@ -1593,7 +1595,7 @@ impl Plan { Some(format_smolstr!("Having ({node_id:?}) has no children!")), ) })?; - let output = self.add_row_for_output(child_id, &[], true)?; + let output = self.add_row_for_output(child_id, &[], true, None)?; *self.get_mut_relation_node(*node_id)?.mut_output() = output; self.replace_parent_in_subtree(output, None, Some(*node_id))?; } -- GitLab