Skip to content

Commit 1c0cda4

Browse files
committed
update
1 parent 0710f55 commit 1c0cda4

1 file changed

Lines changed: 58 additions & 62 deletions

File tree

src/sql/logical_planner/optimizers/chaining.rs

Lines changed: 58 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,99 +10,95 @@
1010
// See the License for the specific language governing permissions and
1111
// limitations under the License.
1212

13-
use std::mem;
14-
15-
use petgraph::graph::{EdgeIndex, NodeIndex};
1613
use petgraph::prelude::*;
17-
use petgraph::visit::NodeRef;
14+
use petgraph::visit::NodeIndexable;
15+
use tracing::debug;
1816

1917
use crate::sql::logical_node::logical::{LogicalEdgeType, LogicalGraph, Optimizer};
2018

21-
pub type NodeId = NodeIndex;
22-
pub type EdgeId = EdgeIndex;
23-
2419
pub struct ChainingOptimizer {}
2520

26-
fn remove_in_place<N, E>(graph: &mut DiGraph<N, E>, node: NodeIndex) {
27-
let incoming = graph.edges_directed(node, Incoming).next().unwrap();
28-
29-
let parent = incoming.source().id();
30-
let incoming = incoming.id();
31-
graph.remove_edge(incoming);
32-
33-
let outgoing: Vec<_> = graph
34-
.edges_directed(node, Outgoing)
35-
.map(|e| (e.id(), e.target().id()))
36-
.collect();
37-
38-
for (edge, target) in outgoing {
39-
let weight = graph.remove_edge(edge).unwrap();
40-
graph.add_edge(parent, target, weight);
41-
}
42-
43-
graph.remove_node(node);
44-
}
45-
4621
impl Optimizer for ChainingOptimizer {
4722
fn optimize_once(&self, plan: &mut LogicalGraph) -> bool {
48-
let node_indices: Vec<NodeIndex> = plan.node_indices().collect();
23+
let mut match_found = None;
4924

50-
for &node_idx in &node_indices {
51-
let cur = plan.node_weight(node_idx).unwrap();
52-
53-
// sources can't be chained
54-
if cur.operator_chain.is_source() {
25+
for node_idx in plan.node_indices() {
26+
let mut outgoing = plan.edges_directed(node_idx, Outgoing);
27+
let first_out = outgoing.next();
28+
if first_out.is_none() || outgoing.next().is_some() {
5529
continue;
5630
}
31+
let edge = first_out.unwrap();
5732

58-
let mut successors = plan.edges_directed(node_idx, Outgoing).collect::<Vec<_>>();
59-
60-
if successors.len() != 1 {
33+
if edge.weight().edge_type != LogicalEdgeType::Forward {
6134
continue;
6235
}
6336

64-
let edge = successors.remove(0);
65-
let edge_type = edge.weight().edge_type;
37+
let target_idx = edge.target();
6638

67-
if edge_type != LogicalEdgeType::Forward {
39+
let mut incoming = plan.edges_directed(target_idx, Incoming);
40+
let first_in = incoming.next();
41+
if first_in.is_none() || incoming.next().is_some() {
6842
continue;
6943
}
7044

71-
let successor_idx = edge.target();
72-
73-
let successor_node = plan.node_weight(successor_idx).unwrap();
45+
let source_node = plan.node_weight(node_idx).expect("Source node missing");
46+
let target_node = plan.node_weight(target_idx).expect("Target node missing");
7447

75-
// skip if parallelism doesn't match or successor is a sink
76-
if cur.parallelism != successor_node.parallelism
77-
|| successor_node.operator_chain.is_sink()
48+
if source_node.operator_chain.is_source()
49+
|| target_node.operator_chain.is_sink()
50+
|| source_node.parallelism != target_node.parallelism
7851
{
7952
continue;
8053
}
8154

82-
// skip successors with multiple predecessors
83-
if plan.edges_directed(successor_idx, Incoming).count() > 1 {
84-
continue;
55+
match_found = Some((node_idx, target_idx, edge.id()));
56+
break;
57+
}
58+
59+
if let Some((source_idx, target_idx, edge_id)) = match_found {
60+
let edge_weight = plan.remove_edge(edge_id).expect("Edge should exist");
61+
62+
let target_outgoing: Vec<_> = plan
63+
.edges_directed(target_idx, Outgoing)
64+
.map(|e| (e.id(), e.target()))
65+
.collect();
66+
67+
for (e_id, next_target_idx) in target_outgoing {
68+
let weight = plan.remove_edge(e_id).expect("Outgoing edge missing");
69+
plan.add_edge(source_idx, next_target_idx, weight);
8570
}
8671

87-
// construct the new node
88-
let mut new_cur = cur.clone();
72+
let is_source_last = source_idx.index() == plan.node_bound() - 1;
8973

90-
new_cur.description = format!("{} -> {}", cur.description, successor_node.description);
74+
let target_node = plan
75+
.remove_node(target_idx)
76+
.expect("Target node should exist");
9177

92-
new_cur
93-
.operator_chain
94-
.operators
95-
.extend(successor_node.operator_chain.operators.clone());
78+
let actual_source_idx = if is_source_last {
79+
target_idx
80+
} else {
81+
source_idx
82+
};
9683

97-
new_cur
98-
.operator_chain
99-
.edges
100-
.push(edge.weight().schema.clone());
84+
let source_node = plan
85+
.node_weight_mut(actual_source_idx)
86+
.expect("Source node missing");
87+
88+
debug!(
89+
"Chaining Optimizer: Fusing '{}' -> '{}'",
90+
source_node.description, target_node.description
91+
);
10192

102-
mem::swap(&mut new_cur, plan.node_weight_mut(node_idx).unwrap());
93+
source_node.description =
94+
format!("{} -> {}", source_node.description, target_node.description);
95+
96+
source_node
97+
.operator_chain
98+
.operators
99+
.extend(target_node.operator_chain.operators);
100+
source_node.operator_chain.edges.push(edge_weight.schema);
103101

104-
// remove the old successor
105-
remove_in_place(plan, successor_idx);
106102
return true;
107103
}
108104

0 commit comments

Comments
 (0)