Skip to content

Commit d7d720a

Browse files
authored
refactor: move all describe, describe_tree and dot-viz code to IR instead of DslPlan (pola-rs#16237)
1 parent 0270ffa commit d7d720a

File tree

27 files changed

+918
-1163
lines changed

27 files changed

+918
-1163
lines changed

crates/polars-lazy/src/dot.rs

+6-50
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,16 @@
1-
use std::fmt::Write;
2-
31
use polars_core::prelude::*;
4-
use polars_plan::dot::*;
5-
use polars_plan::prelude::*;
62

73
use crate::prelude::*;
84

95
impl LazyFrame {
106
/// Get a dot language representation of the LogicalPlan.
117
pub fn to_dot(&self, optimized: bool) -> PolarsResult<String> {
12-
let mut s = String::with_capacity(512);
13-
14-
let mut logical_plan = self.clone().get_plan_builder().build();
15-
if optimized {
16-
// initialize arena's
17-
let mut expr_arena = Arena::with_capacity(64);
18-
let mut lp_arena = Arena::with_capacity(32);
19-
20-
let lp_top = self.clone().optimize_with_scratch(
21-
&mut lp_arena,
22-
&mut expr_arena,
23-
&mut vec![],
24-
true,
25-
)?;
26-
logical_plan = node_to_lp(lp_top, &expr_arena, &mut lp_arena);
27-
}
28-
29-
let prev_node = DotNode {
30-
branch: 0,
31-
id: 0,
32-
fmt: "",
33-
};
34-
35-
// maps graphviz id to label
36-
// we use this to create this graph
37-
// first we create nodes including ids to make sure they are unique
38-
// A [id] -- B [id]
39-
// B [id] -- C [id]
40-
//
41-
// then later we hide the [id] by adding this to the graph
42-
// A [id] [label="A"]
43-
// B [id] [label="B"]
44-
// C [id] [label="C"]
45-
46-
let mut id_map = PlHashMap::with_capacity(8);
47-
logical_plan
48-
.dot(&mut s, (0, 0), prev_node, &mut id_map)
49-
.expect("io error");
50-
s.push('\n');
8+
let lp = if optimized {
9+
self.clone().to_alp_optimized()
10+
} else {
11+
self.clone().to_alp()
12+
}?;
5113

52-
for (id, label) in id_map {
53-
// the label is wrapped in double quotes
54-
// the id already is wrapped in double quotes
55-
writeln!(s, "{id}[label=\"{label}\"]").unwrap();
56-
}
57-
s.push_str("\n}");
58-
Ok(s)
14+
Ok(lp.display_dot().to_string())
5915
}
6016
}

crates/polars-lazy/src/frame/mod.rs

+11-32
Original file line numberDiff line numberDiff line change
@@ -208,49 +208,27 @@ impl LazyFrame {
208208
}
209209

210210
/// Return a String describing the naive (un-optimized) logical plan.
211-
pub fn describe_plan(&self) -> String {
212-
self.logical_plan.describe()
211+
pub fn describe_plan(&self) -> PolarsResult<String> {
212+
Ok(self.clone().to_alp()?.describe())
213213
}
214214

215215
/// Return a String describing the naive (un-optimized) logical plan in tree format.
216-
pub fn describe_plan_tree(&self) -> String {
217-
self.logical_plan.describe_tree_format()
218-
}
219-
220-
fn optimized_plan_ir(&self) -> PolarsResult<IRPlan> {
221-
let mut expr_arena = Arena::with_capacity(64);
222-
let mut lp_arena = Arena::with_capacity(64);
223-
let lp_top = self.clone().optimize_with_scratch(
224-
&mut lp_arena,
225-
&mut expr_arena,
226-
&mut vec![],
227-
true,
228-
)?;
229-
230-
Ok(IRPlan::new(lp_top, lp_arena, expr_arena))
231-
}
232-
233-
fn optimized_plan(&self) -> PolarsResult<DslPlan> {
234-
let IRPlan {
235-
lp_top,
236-
mut lp_arena,
237-
expr_arena,
238-
} = self.optimized_plan_ir()?;
239-
Ok(node_to_lp(lp_top, &expr_arena, &mut lp_arena))
216+
pub fn describe_plan_tree(&self) -> PolarsResult<String> {
217+
Ok(self.clone().to_alp()?.describe_tree_format())
240218
}
241219

242220
/// Return a String describing the optimized logical plan.
243221
///
244222
/// Returns `Err` if optimizing the logical plan fails.
245223
pub fn describe_optimized_plan(&self) -> PolarsResult<String> {
246-
Ok(self.optimized_plan_ir()?.describe())
224+
Ok(self.clone().to_alp_optimized()?.describe())
247225
}
248226

249227
/// Return a String describing the optimized logical plan in tree format.
250228
///
251229
/// Returns `Err` if optimizing the logical plan fails.
252230
pub fn describe_optimized_plan_tree(&self) -> PolarsResult<String> {
253-
Ok(self.optimized_plan()?.describe_tree_format())
231+
Ok(self.clone().to_alp_optimized()?.describe_tree_format())
254232
}
255233

256234
/// Return a String describing the logical plan.
@@ -261,7 +239,7 @@ impl LazyFrame {
261239
if optimized {
262240
self.describe_optimized_plan()
263241
} else {
264-
Ok(self.describe_plan())
242+
self.describe_plan()
265243
}
266244
}
267245

@@ -532,15 +510,16 @@ impl LazyFrame {
532510
self.optimize_with_scratch(lp_arena, expr_arena, &mut vec![], false)
533511
}
534512

535-
pub fn to_alp_optimized(self) -> PolarsResult<(Node, Arena<IR>, Arena<AExpr>)> {
513+
pub fn to_alp_optimized(self) -> PolarsResult<IRPlan> {
536514
let mut lp_arena = Arena::with_capacity(16);
537515
let mut expr_arena = Arena::with_capacity(16);
538516
let node =
539517
self.optimize_with_scratch(&mut lp_arena, &mut expr_arena, &mut vec![], false)?;
540-
Ok((node, lp_arena, expr_arena))
518+
519+
Ok(IRPlan::new(node, lp_arena, expr_arena))
541520
}
542521

543-
pub fn to_alp(self) -> PolarsResult<(Node, Arena<IR>, Arena<AExpr>)> {
522+
pub fn to_alp(self) -> PolarsResult<IRPlan> {
544523
self.logical_plan.to_alp()
545524
}
546525

crates/polars-lazy/src/physical_plan/expressions/apply.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl ApplyExpr {
3838
) -> Self {
3939
#[cfg(debug_assertions)]
4040
if matches!(options.collect_groups, ApplyOptions::ElementWise) && options.returns_scalar {
41-
panic!("expr {} is not implemented correctly. 'returns_scalar' and 'elementwise' are mutually exclusive", expr)
41+
panic!("expr {:?} is not implemented correctly. 'returns_scalar' and 'elementwise' are mutually exclusive", expr)
4242
}
4343

4444
Self {

crates/polars-lazy/src/physical_plan/expressions/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl<'a> AggregationContext<'a> {
341341
(true, &DataType::List(_)) => {
342342
if series.len() != self.groups.len() {
343343
let fmt_expr = if let Some(e) = expr {
344-
format!("'{e}' ")
344+
format!("'{e:?}' ")
345345
} else {
346346
String::new()
347347
};
@@ -589,7 +589,7 @@ impl Display for &dyn PhysicalExpr {
589589
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
590590
match self.as_expression() {
591591
None => Ok(()),
592-
Some(e) => write!(f, "{e}"),
592+
Some(e) => write!(f, "{e:?}"),
593593
}
594594
}
595595
}

crates/polars-lazy/src/physical_plan/streaming/tree.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,15 @@ pub(super) fn dbg_tree(tree: Tree, lp_arena: &Arena<IR>, expr_arena: &Arena<AExp
177177
.unwrap();
178178

179179
println!("SUBPLAN ELIGIBLE FOR STREAMING:");
180-
let lp = node_to_lp(root, expr_arena, &mut (lp_arena.clone()));
181-
println!("{lp:?}\n");
180+
println!(
181+
"{}\n",
182+
IRPlanRef {
183+
lp_top: root,
184+
lp_arena,
185+
expr_arena
186+
}
187+
.display()
188+
);
182189

183190
println!("PIPELINE TREE:");
184191
for (i, branch) in tree.iter().enumerate() {

crates/polars-lazy/src/tests/cse.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ fn cached_before_root(q: LazyFrame) {
1111
}
1212

1313
fn count_caches(q: LazyFrame) -> usize {
14-
let (node, lp_arena, _) = q.to_alp_optimized().unwrap();
14+
let IRPlan {
15+
lp_top, lp_arena, ..
16+
} = q.to_alp_optimized().unwrap();
1517
(&lp_arena)
16-
.iter(node)
18+
.iter(lp_top)
1719
.filter(|(_node, lp)| matches!(lp, IR::Cache { .. }))
1820
.count()
1921
}

crates/polars-lazy/src/tests/io.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,10 @@ fn test_scan_parquet_limit_9001() {
391391
..Default::default()
392392
};
393393
let q = LazyFrame::scan_parquet(path, args).unwrap().limit(3);
394-
let (node, lp_arena, _) = q.to_alp_optimized().unwrap();
395-
(&lp_arena).iter(node).all(|(_, lp)| match lp {
394+
let IRPlan {
395+
lp_top, lp_arena, ..
396+
} = q.to_alp_optimized().unwrap();
397+
(&lp_arena).iter(lp_top).all(|(_, lp)| match lp {
396398
IR::Union { options, .. } => {
397399
let sliced = options.slice.unwrap();
398400
sliced.1 == 3

crates/polars-lazy/src/tests/logical.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn test_duration() -> PolarsResult<()> {
5252
}
5353

5454
fn print_plans(lf: &LazyFrame) {
55-
println!("LOGICAL PLAN\n\n{}\n", lf.describe_plan());
55+
println!("LOGICAL PLAN\n\n{}\n", lf.describe_plan().unwrap());
5656
println!(
5757
"OPTIMIZED LOGICAL PLAN\n\n{}\n",
5858
lf.describe_optimized_plan().unwrap()

crates/polars-lazy/src/tests/schema.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ fn test_schema_update_after_projection_pd() -> PolarsResult<()> {
1616

1717
// run optimizations
1818
// Get the explode node
19-
let (input, lp_arena, _expr_arena) = q.to_alp_optimized()?;
19+
let IRPlan {
20+
lp_top,
21+
lp_arena,
22+
expr_arena: _,
23+
} = q.to_alp_optimized()?;
2024

2125
// assert the schema has been corrected with the projection pushdown run
22-
let lp = lp_arena.get(input);
26+
let lp = lp_arena.get(lp_top);
2327
assert!(matches!(
2428
lp,
2529
IR::MapFunction {

crates/polars-lazy/src/tests/tpch.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ fn test_q2() -> PolarsResult<()> {
8585
.limit(100)
8686
.with_comm_subplan_elim(true);
8787

88-
let (node, lp_arena, _) = q.clone().to_alp_optimized().unwrap();
88+
let IRPlan {
89+
lp_top, lp_arena, ..
90+
} = q.clone().to_alp_optimized().unwrap();
8991
assert_eq!(
9092
(&lp_arena)
91-
.iter(node)
93+
.iter(lp_top)
9294
.filter(|(_, alp)| matches!(alp, IR::Cache { .. }))
9395
.count(),
9496
2

0 commit comments

Comments
 (0)