From 29b7bd56cd7dd8158f94fb61213b1f56422ca23f Mon Sep 17 00:00:00 2001 From: Arseniy Volynets <a.volynets@picodata.io> Date: Mon, 28 Oct 2024 13:33:29 +0300 Subject: [PATCH] fix: incorrect equality cols for Eq - In case we have equality between columns of the same table, `eq_cols_from_eq` should return empty equality cols, but it returned None, which led to wrong motion. Fixed that. - It was found after a merge tuples transform fix, in front_sql_join_single_left_5 test where now there are two equalities instead of one. Earlier, there always was one equality because merge tuples produced a single (..) = (..) term for an and-chain. And this test didn't work, because this term contained one equality pair. Now there are two terms: (..) = (..) and (..)=(..) and one of them does not contain any equality pairs. --- .../transformation/redistribution/eq_cols.rs | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs b/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs index 277adcb143..4953bf71c4 100644 --- a/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs +++ b/sbroad-core/src/ir/transformation/redistribution/eq_cols.rs @@ -169,7 +169,7 @@ type OutputColOuter = usize; /// is a subexpression of a bigger expression, then there's a chance for it: /// ... on i.a = i.b (repartition join is not possible) eq cols: [] /// ... on i.a = i.b and i.a = o.b (repartition join is possible) eq cols: [(a, b)] -#[derive(Default)] +#[derive(Default, Debug)] pub struct EqualityCols { pub pairs: Vec<(OutputColInner, OutputColOuter)>, distinct_inner: HashSet<OutputColInner>, @@ -191,6 +191,7 @@ pub struct EqualityCols { /// On the other hand, if the join condition consists only of left side of `and`: /// `... on i.a = 3` /// Then repartition join is not possible for such condition. +#[derive(Debug)] pub struct EqualityColsMap(HashMap<ExpressionId, EqualityCols>); impl EqualityColsMap { @@ -293,6 +294,7 @@ impl EqualityCols { list_right: &[NodeId], node_id: NodeId, inner_id: NodeId, + outer_id: NodeId, plan: &Plan, refers_to: &ReferredMap, ) -> Result<Option<EqualityCols>, SbroadError> { @@ -304,37 +306,40 @@ impl EqualityCols { match (left_node, right_node) { ( Expression::Reference(Reference { - targets: targets_left, position: pos_left, parent: parent_left, col_type: col_type_left, asterisk_source: asterisk_source_left, + .. }), Expression::Reference(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. // if one Reference refers to one child, and the second one refers to another one, // then we have an equality pair - if targets_left != targets_right - && parent_left == parent_right + if 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)?; - let (inner_pos, outer_pos) = if left_referred_child_id == inner_id { - (*pos_left, *pos_right) - } else { - (*pos_right, *pos_left) - }; - new_eq_cols.add_equality_pair(inner_pos, outer_pos); + let right_referred_child_id = + plan.get_relational_from_reference_node(*right_id)?; + if left_referred_child_id == inner_id && right_referred_child_id == outer_id + { + new_eq_cols.add_equality_pair(*pos_left, *pos_right); + } else if left_referred_child_id == outer_id + && right_referred_child_id == inner_id + { + new_eq_cols.add_equality_pair(*pos_right, *pos_left); + } }; } (Expression::Constant(_), _) | (_, Expression::Constant(_)) => {} @@ -349,7 +354,7 @@ impl EqualityCols { } } } - if is_repartition_join_possible && !new_eq_cols.is_empty() { + if is_repartition_join_possible { Ok(Some(new_eq_cols)) } else { Ok(None) @@ -369,6 +374,7 @@ impl EqualityCols { node_id: NodeId, refers_to: &ReferredMap, inner_id: NodeId, + outer_id: NodeId, plan: &Plan, ) -> Result<Option<EqualityCols>, SbroadError> { let left_expr = plan.get_expression_node(op.left)?; @@ -383,7 +389,7 @@ impl EqualityCols { }), ) => match op.op { Bool::Eq | Bool::In => EqualityCols::eq_cols_for_eq( - list_left, list_right, node_id, inner_id, plan, refers_to, + list_left, list_right, node_id, inner_id, outer_id, plan, refers_to, )?, _ => { if let Some(Referred::Both) = refers_to.get(node_id) { @@ -502,6 +508,7 @@ impl EqualityCols { condition_id: NodeId, ) -> Result<Option<EqualityCols>, SbroadError> { let mut node_eq_cols: EqualityColsMap = EqualityColsMap::new(); + let outer_id = plan.get_relational_child(join_id, 0)?; let refers_to = ReferredMap::new_from_join_condition(plan, condition_id, join_id)?; let filter = |node_id: NodeId| -> bool { if let Ok(Node::Expression(Expression::Bool(_))) = plan.get_node(node_id) { @@ -520,9 +527,9 @@ impl EqualityCols { let left_expr = plan.get_expression_node(bool_op.left)?; let right_expr = plan.get_expression_node(bool_op.right)?; let new_eq_cols = match (left_expr, right_expr) { - (Expression::Row(_), Expression::Row(_)) => { - EqualityCols::eq_cols_for_rows(&bool_op, node_id, &refers_to, inner_id, plan)? - } + (Expression::Row(_), Expression::Row(_)) => EqualityCols::eq_cols_for_rows( + &bool_op, node_id, &refers_to, inner_id, outer_id, plan, + )?, (_, _) => { EqualityCols::eq_cols_for_bool(&bool_op, node_id, &refers_to, &mut node_eq_cols) } -- GitLab