From 5553b0c1a45f003974ce91a5a0a03c39e0a8aa06 Mon Sep 17 00:00:00 2001 From: Denis Smirnov <sd@picodata.io> Date: Mon, 31 Jan 2022 17:05:15 +0700 Subject: [PATCH] fix: resolve conflicts on rebase --- src/ir/distribution.rs | 56 +++++++++---------- src/ir/expression.rs | 31 +++++----- src/ir/expression/tests.rs | 8 +-- src/ir/transformation/redistribution.rs | 51 +++++++---------- src/ir/transformation/redistribution/tests.rs | 11 ++-- .../full_motion_less_for_sub_query.yaml | 6 ++ ...otion_non_segment_outer_for_sub_query.yaml | 6 ++ .../redistribution/local_sub_query.yaml | 6 ++ .../redistribution/multiple_sub_queries.yaml | 14 ++++- .../segment_motion_for_sub_query.yaml | 6 ++ 10 files changed, 109 insertions(+), 86 deletions(-) diff --git a/src/ir/distribution.rs b/src/ir/distribution.rs index c5bc6cb89a..a5b59b15c6 100644 --- a/src/ir/distribution.rs +++ b/src/ir/distribution.rs @@ -122,38 +122,36 @@ impl Plan { .. }) = self.get_node(node_id)? { - // Get a relational node, containing current row. - parent_node = Some(*id_map.get(parent).ok_or(QueryPlannerError::InvalidNode)?); - if let Node::Relational(relational_op) = - self.get_node(parent_node.ok_or(QueryPlannerError::InvalidNode)?)? - { - if let Some(children) = relational_op.children() { - // References in the branch node. - let child_pos_list: &Vec<usize> = targets - .as_ref() - .ok_or(QueryPlannerError::InvalidReference)?; - for target in child_pos_list { - let child_node: usize = *children - .get(*target) - .ok_or(QueryPlannerError::ValueOutOfRange)?; - child_set.insert(child_node); - child_pos_map.insert((child_node, *position), pos); - } - } else { - // References in the leaf (relation scan) node. - if targets.is_some() { - return Err(QueryPlannerError::InvalidReference); - } - if let Relational::ScanRelation { relation, .. } = relational_op { - table_set.insert(relation.clone()); - table_pos_map.insert(*position, pos); - } else { - return Err(QueryPlannerError::InvalidReference); - } + parent_node = Some(self.get_map_relational_value(*parent)?); + let relational_op = + self.get_relation_node(parent_node.ok_or(QueryPlannerError::InvalidRelation)?)?; + + if let Some(children) = relational_op.children() { + // References in the branch node. + let child_pos_list: &Vec<usize> = targets + .as_ref() + .ok_or(QueryPlannerError::InvalidReference)?; + for target in child_pos_list { + let child_node: usize = *children + .get(*target) + .ok_or(QueryPlannerError::ValueOutOfRange)?; + child_set.insert(child_node); + child_pos_map.insert((child_node, *position), pos); } } else { - return Err(QueryPlannerError::InvalidNode); + // References in the leaf (relation scan) node. + if targets.is_some() { + return Err(QueryPlannerError::InvalidReference); + } + if let Relational::ScanRelation { relation, .. } = relational_op { + table_set.insert(relation.clone()); + table_pos_map.insert(*position, pos); + } else { + return Err(QueryPlannerError::InvalidReference); + } } + } else { + return Err(QueryPlannerError::InvalidNode); } Ok(()) }; diff --git a/src/ir/expression.rs b/src/ir/expression.rs index e3cb4ea1fd..1a5f0a0094 100644 --- a/src/ir/expression.rs +++ b/src/ir/expression.rs @@ -11,7 +11,7 @@ use super::value::Value; use super::{Node, Nodes, Plan}; use crate::errors::QueryPlannerError; use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use traversal::DftPost; /// Tuple tree build blocks. @@ -507,30 +507,35 @@ impl Plan { /// /// # Errors /// - reference is invalid + /// - `relational_map` is not initialized pub fn get_relational_from_reference_node( &self, ref_id: usize, - map: &HashMap<usize, usize>, ) -> Result<HashSet<usize>, QueryPlannerError> { let mut rel_nodes: HashSet<usize> = HashSet::new(); + if self.relational_map.is_none() { + return Err(QueryPlannerError::CustomError(String::from( + "Initialized relational map in the plan", + ))); + } + if let Node::Expression(Expression::Reference { targets, parent, .. }) = self.get_node(ref_id)? { - if let Some(rel_id) = map.get(parent) { - if let Node::Relational(rel) = self.get_node(*rel_id)? { - if let Some(children) = rel.children() { - if let Some(positions) = targets { - for pos in positions { - if let Some(child) = children.get(*pos) { - rel_nodes.insert(*child); - } + let referred_rel_id = self.get_map_relational_value(*parent)?; + if let Node::Relational(rel) = self.get_node(referred_rel_id)? { + if let Some(children) = rel.children() { + if let Some(positions) = targets { + for pos in positions { + if let Some(child) = children.get(*pos) { + rel_nodes.insert(*child); } } } - return Ok(rel_nodes); } + return Ok(rel_nodes); } } Err(QueryPlannerError::InvalidReference) @@ -541,10 +546,10 @@ impl Plan { /// # Errors /// - node is not row /// - row is invalid + /// - `relational_map` is not initialized pub fn get_relational_from_row_nodes( &self, row_id: usize, - map: &HashMap<usize, usize>, ) -> Result<HashSet<usize>, QueryPlannerError> { let mut rel_nodes: HashSet<usize> = HashSet::new(); @@ -552,7 +557,7 @@ impl Plan { let post_tree = DftPost::new(&row_id, |node| self.nodes.expr_iter(node, false)); for (_, node) in post_tree { if let Node::Expression(Expression::Reference { .. }) = self.get_node(*node)? { - rel_nodes.extend(&self.get_relational_from_reference_node(*node, map)?); + rel_nodes.extend(&self.get_relational_from_reference_node(*node)?); } } return Ok(rel_nodes); diff --git a/src/ir/expression/tests.rs b/src/ir/expression/tests.rs index 1bd82ad18b..c275dda323 100644 --- a/src/ir/expression/tests.rs +++ b/src/ir/expression/tests.rs @@ -30,8 +30,8 @@ fn rel_nodes_from_reference_in_scan() { let scan_id = plan.add_scan("t").unwrap(); let output = plan.get_relational_output(scan_id).unwrap(); - let map = plan.relational_id_map(); - let rel_set = plan.get_relational_from_row_nodes(output, &map).unwrap(); + plan.build_relational_map(); + let rel_set = plan.get_relational_from_row_nodes(output).unwrap(); assert_eq!(true, rel_set.is_empty()); } @@ -47,8 +47,8 @@ fn rel_nodes_from_reference_in_proj() { let proj_id = plan.add_proj(scan_id, &["a"]).unwrap(); let output = plan.get_relational_output(proj_id).unwrap(); - let map = plan.relational_id_map(); - let rel_set = plan.get_relational_from_row_nodes(output, &map).unwrap(); + plan.build_relational_map(); + let rel_set = plan.get_relational_from_row_nodes(output).unwrap(); assert_eq!(1, rel_set.len()); assert_eq!(Some(&scan_id), rel_set.get(&scan_id)); } diff --git a/src/ir/transformation/redistribution.rs b/src/ir/transformation/redistribution.rs index bde7ab382e..0748c98fd1 100644 --- a/src/ir/transformation/redistribution.rs +++ b/src/ir/transformation/redistribution.rs @@ -28,21 +28,17 @@ struct BoolOp { impl BoolOp { fn from_expr(plan: &Plan, expr_id: usize) -> Result<Self, QueryPlannerError> { - if let Node::Expression(expr) = plan.get_node(expr_id)? { - if let Expression::Bool { - left, op, right, .. - } = expr - { - Ok(BoolOp { - left: *left, - op: op.clone(), - right: *right, - }) - } else { - Err(QueryPlannerError::InvalidBool) - } + if let Expression::Bool { + left, op, right, .. + } = plan.get_expression_node(expr_id)? + { + Ok(BoolOp { + left: *left, + op: op.clone(), + right: *right, + }) } else { - Err(QueryPlannerError::InvalidNode) + Err(QueryPlannerError::InvalidBool) } } } @@ -97,13 +93,13 @@ impl Plan { /// /// # Errors /// - reference points to multiple sub-queries (invalid SQL) + /// - `relational_map` is not initialized fn get_sub_query_from_row_node( &self, ref_id: usize, - map: &HashMap<usize, usize>, ) -> Result<Option<usize>, QueryPlannerError> { let mut sq_set: HashSet<usize> = HashSet::new(); - let rel_nodes = self.get_relational_from_row_nodes(ref_id, map)?; + let rel_nodes = self.get_relational_from_row_nodes(ref_id)?; for rel_id in rel_nodes { if let Node::Relational(Relational::ScanSubQuery { .. }) = self.get_node(rel_id)? { sq_set.insert(rel_id); @@ -209,20 +205,19 @@ impl Plan { fn resolve_sub_query_conflicts( &mut self, expr_id: usize, - map: &HashMap<usize, usize>, ) -> Result<HashMap<usize, MotionPolicy>, QueryPlannerError> { let nodes = self.get_bool_nodes_with_row_children(expr_id)?; for node in &nodes { let bool_op = BoolOp::from_expr(self, *node)?; - self.set_distribution(bool_op.left, map)?; - self.set_distribution(bool_op.right, map)?; + self.set_distribution(bool_op.left)?; + self.set_distribution(bool_op.right)?; } let mut strategy: HashMap<usize, MotionPolicy> = HashMap::new(); for node in &nodes { let bool_op = BoolOp::from_expr(self, *node)?; - let left = self.get_sub_query_from_row_node(bool_op.left, map)?; - let right = self.get_sub_query_from_row_node(bool_op.right, map)?; + let left = self.get_sub_query_from_row_node(bool_op.left)?; + let right = self.get_sub_query_from_row_node(bool_op.right)?; match left { Some(left_sq) => { match right { @@ -269,22 +264,18 @@ impl Plan { /// - failed to resolve distribution conflicts /// - failed to set distribution pub fn add_motions(&mut self) -> Result<(), QueryPlannerError> { - let map = self.relational_id_map(); + self.build_relational_map(); let nodes = self.get_relational_nodes_dfs_post()?; for id in &nodes { - let rel_op: Relational = match self.get_node(*id)? { - Node::Expression(_) => return Err(QueryPlannerError::InvalidNode), - Node::Relational(rel) => rel.clone(), - }; - match rel_op { + match self.get_relation_node(*id)?.clone() { // At the moment our grammar and IR constructor // don't support projection with sub queries. Relational::Projection { output, .. } | Relational::ScanRelation { output, .. } | Relational::ScanSubQuery { output, .. } | Relational::UnionAll { output, .. } => { - self.set_distribution(output, &map)?; + self.set_distribution(output)?; } Relational::Motion { .. } => { // We can apply this transformation only once, @@ -294,9 +285,9 @@ impl Plan { ))); } Relational::Selection { output, filter, .. } => { - let strategy = self.resolve_sub_query_conflicts(filter, &map)?; + let strategy = self.resolve_sub_query_conflicts(filter)?; self.create_motion_nodes(*id, &strategy)?; - self.set_distribution(output, &map)?; + self.set_distribution(output)?; } Relational::InnerJoin { .. } => { // TODO: resolve join conflicts and set the output row distribution diff --git a/src/ir/transformation/redistribution/tests.rs b/src/ir/transformation/redistribution/tests.rs index d949ee4f42..b59d63f73b 100644 --- a/src/ir/transformation/redistribution/tests.rs +++ b/src/ir/transformation/redistribution/tests.rs @@ -44,22 +44,19 @@ fn segment_motion_for_sub_query() { let select_id = plan.add_select(&children[..], eq_id, id).unwrap(); plan.set_top(select_id).unwrap(); - let map = plan.relational_id_map(); + plan.build_relational_map(); let mut expected_rel_set: HashSet<usize> = HashSet::new(); expected_rel_set.insert(sq_id); assert_eq!( expected_rel_set, - plan.get_relational_from_row_nodes(b_id, &map).unwrap() - ); - assert_eq!( - Some(sq_id), - plan.get_sub_query_from_row_node(b_id, &map).unwrap() + plan.get_relational_from_row_nodes(b_id).unwrap() ); + assert_eq!(Some(sq_id), plan.get_sub_query_from_row_node(b_id).unwrap()); assert_eq!( QueryPlannerError::UninitializedDistribution, - plan.resolve_sub_query_conflicts(eq_id, &map).unwrap_err() + plan.resolve_sub_query_conflicts(eq_id).unwrap_err() ); plan.add_motions().unwrap(); diff --git a/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml b/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml index d82f83c30b..00420543e6 100644 --- a/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml +++ b/tests/artifactory/ir/transformation/redistribution/full_motion_less_for_sub_query.yaml @@ -201,6 +201,12 @@ relations: positions: - 0 name: t1 +relational_map: + 0: 3 + 10: 13 + 4: 9 + 14: 17 + 18: 26 slices: - - 30 diff --git a/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml b/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml index 6afe1446c5..da7e3014ba 100644 --- a/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml +++ b/tests/artifactory/ir/transformation/redistribution/full_motion_non_segment_outer_for_sub_query.yaml @@ -220,6 +220,12 @@ relations: positions: - 0 name: t2 +relational_map: + 0: 5 + 10: 13 + 14: 17 + 18: 28 + 6: 9 slices: - - 32 diff --git a/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml b/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml index e296537760..df8921440f 100644 --- a/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml +++ b/tests/artifactory/ir/transformation/redistribution/local_sub_query.yaml @@ -179,5 +179,11 @@ relations: positions: - 0 name: t2 +relational_map: + 8: 11 + 0: 3 + 4: 7 + 12: 15 + 16: 24 slices: ~ top: 24 diff --git a/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml b/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml index a55d631166..48250d984a 100644 --- a/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml +++ b/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml @@ -351,8 +351,16 @@ relations: positions: - 0 name: t2 -slices: - - - - 50 +relational_map: + 28: 31 + 24: 27 + 14: 17 + 32: 46 + 10: 13 + 4: 9 + 0: 3 + 18: 23 +slices: + - - 50 - 54 top: 46 diff --git a/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml b/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml index 6eae3d01b8..614dee176f 100644 --- a/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml +++ b/tests/artifactory/ir/transformation/redistribution/segment_motion_for_sub_query.yaml @@ -207,6 +207,12 @@ relations: positions: - 0 name: t2 +relational_map: + 18: 26 + 10: 13 + 0: 3 + 4: 9 + 14: 17 slices: - - 30 -- GitLab