diff --git a/src/ir/transformation/redistribution.rs b/src/ir/transformation/redistribution.rs index 3beb7a701724008d15c1acf4501bb490edd8b3d6..5ec36eba53c2e60974c8cc372bc4aae77590e526 100644 --- a/src/ir/transformation/redistribution.rs +++ b/src/ir/transformation/redistribution.rs @@ -63,17 +63,31 @@ impl Plan { Ok(nodes) } - /// Get boolean expressions in the sub-tree. + /// Get boolean expressions with row children in the sub-tree. /// /// # Errors /// - some of the expression nodes are invalid - fn get_bool_nodes_dfs_post(&self, top: usize) -> Result<Vec<usize>, QueryPlannerError> { + fn get_bool_nodes_with_row_children( + &self, + top: usize, + ) -> Result<Vec<usize>, QueryPlannerError> { let mut nodes: Vec<usize> = Vec::new(); let post_tree = DftPost::new(&top, |node| self.nodes.expr_iter(node, false)); for (_, node) in post_tree { - if let Node::Expression(Expression::Bool { .. }) = self.get_node(*node)? { - nodes.push(*node); + // Append only booleans with row children. + if let Node::Expression(Expression::Bool { left, right, .. }) = self.get_node(*node)? { + let left_is_row = matches!( + self.get_node(*left)?, + Node::Expression(Expression::Row { .. }) + ); + let right_is_row = matches!( + self.get_node(*right)?, + Node::Expression(Expression::Row { .. }) + ); + if left_is_row && right_is_row { + nodes.push(*node); + } } } Ok(nodes) @@ -197,7 +211,7 @@ impl Plan { expr_id: usize, map: &HashMap<usize, usize>, ) -> Result<HashMap<usize, MotionPolicy>, QueryPlannerError> { - let nodes = self.get_bool_nodes_dfs_post(expr_id)?; + 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)?; @@ -292,6 +306,8 @@ impl Plan { } } } + + // TODO: gather motions (revert bft) Ok(()) } } diff --git a/src/ir/transformation/redistribution/tests.rs b/src/ir/transformation/redistribution/tests.rs index 71212a21e1a6ef1bc0b3869222955213e4d130b5..d949ee4f42aa8e4c934b1f31fb0c37244a096187 100644 --- a/src/ir/transformation/redistribution/tests.rs +++ b/src/ir/transformation/redistribution/tests.rs @@ -231,3 +231,76 @@ fn local_sub_query() { let expected_plan = Plan::from_yaml(&s).unwrap(); assert_eq!(plan, expected_plan); } + +#[test] +fn multiple_sub_queries() { + // t1(a int) key [a] + // t2(a int, b int) key [a] + // select * from t1 where a < (select a from t2) or a = (select b from t2) + let mut plan = Plan::new(); + let mut children: Vec<usize> = Vec::new(); + + let t1 = Table::new_seg("t1", vec![Column::new("a", Type::Integer)], &["a"]).unwrap(); + plan.add_rel(t1); + let scan_t1_id = plan.add_scan("t1").unwrap(); + children.push(scan_t1_id); + + let t2 = Table::new_seg( + "t2", + vec![ + Column::new("a", Type::Integer), + Column::new("b", Type::Integer), + ], + &["a"], + ) + .unwrap(); + plan.add_rel(t2); + let sq1_scan_t2_id = plan.add_scan("t2").unwrap(); + let sq1_proj_id = plan.add_proj(sq1_scan_t2_id, &["a"]).unwrap(); + let sq1_id = plan.add_sub_query(sq1_proj_id, None).unwrap(); + children.push(sq1_id); + let sq1_pos = children.len() - 1; + + let sq2_scan_t2_id = plan.add_scan("t2").unwrap(); + let sq2_proj_id = plan.add_proj(sq2_scan_t2_id, &["b"]).unwrap(); + let sq2_id = plan.add_sub_query(sq2_proj_id, None).unwrap(); + children.push(sq2_id); + let sq2_pos = children.len() - 1; + + let id = plan.nodes.next_id(); + let sq1_inner_a_id = plan + .add_row_from_sub_query(id, &children[..], sq1_pos, &["a"]) + .unwrap(); + let sq1_outer_a_id = plan.add_row_from_child(id, scan_t1_id, &["a"]).unwrap(); + let less_id = plan + .add_bool(sq1_outer_a_id, Bool::Lt, sq1_inner_a_id) + .unwrap(); + + let sq2_inner_a_id = plan + .add_row_from_sub_query(id, &children[..], sq2_pos, &["b"]) + .unwrap(); + let sq2_outer_a_id = plan.add_row_from_child(id, scan_t1_id, &["a"]).unwrap(); + let eq_id = plan + .add_bool(sq2_outer_a_id, Bool::Eq, sq2_inner_a_id) + .unwrap(); + + let or_id = plan.add_bool(less_id, Bool::Or, eq_id).unwrap(); + + let select_id = plan.add_select(&children[..], or_id, id).unwrap(); + plan.set_top(select_id).unwrap(); + + plan.add_motions().unwrap(); + + // Check the modified plan + plan.nodes.add_new_equalities().unwrap(); + let path = Path::new("") + .join("tests") + .join("artifactory") + .join("ir") + .join("transformation") + .join("redistribution") + .join("multiple_sub_queries.yaml"); + let s = fs::read_to_string(path).unwrap(); + let expected_plan = Plan::from_yaml(&s).unwrap(); + assert_eq!(plan, expected_plan); +} diff --git a/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml b/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7919152d0c3213c011500495ccc84a2be211258b --- /dev/null +++ b/tests/artifactory/ir/transformation/redistribution/multiple_sub_queries.yaml @@ -0,0 +1,355 @@ +--- +nodes: + arena: + - Expression: + Reference: + targets: ~ + position: 0 + parent: 0 + - Expression: + Alias: + name: a + child: 0 + - Expression: + Row: + list: + - 1 + distribution: + Segment: + keys: + - positions: + - 0 + - Relational: + ScanRelation: + output: 2 + id: 0 + relation: t1 + - Expression: + Reference: + targets: ~ + position: 0 + parent: 4 + - Expression: + Alias: + name: a + child: 4 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 4 + - Expression: + Alias: + name: b + child: 6 + - Expression: + Row: + list: + - 5 + - 7 + distribution: + Segment: + keys: + - positions: + - 0 + - Relational: + ScanRelation: + output: 8 + id: 4 + relation: t2 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 10 + - Expression: + Alias: + name: a + child: 10 + - Expression: + Row: + list: + - 11 + distribution: + Segment: + keys: + - positions: + - 0 + - Relational: + Projection: + children: + - 9 + id: 10 + output: 12 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 14 + - Expression: + Alias: + name: a + child: 14 + - Expression: + Row: + list: + - 15 + distribution: + Segment: + keys: + - positions: + - 0 + - Relational: + ScanSubQuery: + alias: ~ + children: + - 13 + id: 14 + output: 16 + - Expression: + Reference: + targets: ~ + position: 0 + parent: 18 + - Expression: + Alias: + name: a + child: 18 + - Expression: + Reference: + targets: ~ + position: 1 + parent: 18 + - Expression: + Alias: + name: b + child: 20 + - Expression: + Row: + list: + - 19 + - 21 + distribution: + Segment: + keys: + - positions: + - 0 + - Relational: + ScanRelation: + output: 22 + id: 18 + relation: t2 + - Expression: + Reference: + targets: + - 0 + position: 1 + parent: 24 + - Expression: + Alias: + name: b + child: 24 + - Expression: + Row: + list: + - 25 + distribution: Any + - Relational: + Projection: + children: + - 23 + id: 24 + output: 26 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 28 + - Expression: + Alias: + name: b + child: 28 + - Expression: + Row: + list: + - 29 + distribution: Any + - Relational: + ScanSubQuery: + alias: ~ + children: + - 27 + id: 28 + output: 30 + - Expression: + Reference: + targets: + - 1 + position: 0 + parent: 32 + - Expression: + Row: + list: + - 32 + distribution: + Segment: + keys: + - positions: + - 0 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 32 + - Expression: + Row: + list: + - 34 + distribution: + Segment: + keys: + - positions: + - 0 + - Expression: + Bool: + left: 35 + op: Lt + right: 33 + - Expression: + Reference: + targets: + - 2 + position: 0 + parent: 32 + - Expression: + Row: + list: + - 37 + distribution: Any + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 32 + - Expression: + Row: + list: + - 39 + distribution: + Segment: + keys: + - positions: + - 0 + - Expression: + Bool: + left: 40 + op: Eq + right: 38 + - Expression: + Bool: + left: 36 + op: Or + right: 41 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 32 + - Expression: + Alias: + name: a + child: 43 + - Expression: + Row: + list: + - 44 + distribution: + Segment: + keys: + - positions: + - 0 + - Relational: + Selection: + children: + - 3 + - 50 + - 54 + filter: 42 + id: 32 + output: 45 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 47 + - Expression: + Alias: + name: a + child: 47 + - Expression: + Row: + list: + - 48 + distribution: ~ + - Relational: + Motion: + children: + - 17 + id: 47 + policy: Full + output: 49 + - Expression: + Reference: + targets: + - 0 + position: 0 + parent: 51 + - Expression: + Alias: + name: b + child: 51 + - Expression: + Row: + list: + - 52 + distribution: ~ + - Relational: + Motion: + children: + - 31 + id: 51 + policy: + Segment: + positions: + - 0 + output: 53 +relations: + t1: + Segment: + columns: + - name: a + type: integer + key: + positions: + - 0 + name: t1 + t2: + Segment: + columns: + - name: a + type: integer + - name: b + type: integer + key: + positions: + - 0 + name: t2 +slices: ~ +top: 46