Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions datafusion/physical-plan/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,18 @@ pub enum DisplayFormatType {
/// information for understanding a plan. It should NOT contain the same level
/// of detail information as the [`Self::Default`] format.
///
/// In this mode, each line contains a key=value pair.
/// Everything before the first `=` is treated as the key, and everything after the
/// first `=` is treated as the value.
/// In this mode, each line has one of two formats:
///
/// 1. A string without a `=`, which is printed in its own line
///
/// 2. A string with a `=` that is treated as a `key=value pair`. Everything
/// before the first `=` is treated as the key, and everything after the
/// first `=` is treated as the value.
///
/// For example, if the output of `TreeRender` is this:
/// ```text
/// Parquet
/// partition_sizes=[1]
/// partitions=1
/// ```
///
/// It is rendered in the center of a box in the following way:
Expand All @@ -69,7 +73,7 @@ pub enum DisplayFormatType {
/// │ DataSourceExec │
/// │ -------------------- │
/// │ partition_sizes: [1] │
/// │ partitions: 1
/// │ Parquet
/// └───────────────────────────┘
/// ```
TreeRender,
Expand Down Expand Up @@ -857,22 +861,24 @@ impl TreeRenderVisitor<'_, '_> {
let sorted_extra_info: BTreeMap<_, _> = extra_info.iter().collect();
for (key, value) in sorted_extra_info {
let mut str = Self::remove_padding(value);
if str.is_empty() {
continue;
}
let mut is_inlined = false;
let available_width = Self::NODE_RENDER_WIDTH - 7;
let total_size = key.len() + str.len() + 2;
let is_multiline = str.contains('\n');
if !is_multiline && total_size < available_width {

if str.is_empty() {
str = key.to_string();
} else if !is_multiline && total_size < available_width {
str = format!("{}: {}", key, str);
is_inlined = true;
} else {
str = format!("{}:\n{}", key, str);
}

if is_inlined && was_inlined {
requires_padding = false;
}

if requires_padding {
result.push(String::new());
}
Expand Down
8 changes: 5 additions & 3 deletions datafusion/physical-plan/src/joins/cross_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,13 @@ impl DisplayAs for CrossJoinExec {
f: &mut std::fmt::Formatter,
) -> std::fmt::Result {
match t {
DisplayFormatType::Default
| DisplayFormatType::Verbose
| DisplayFormatType::TreeRender => {
DisplayFormatType::Default | DisplayFormatType::Verbose => {
write!(f, "CrossJoinExec")
}
DisplayFormatType::TreeRender => {
// no extra info to display
Ok(())
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/render_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,12 @@ fn create_tree_recursive(
let mut extra_info = HashMap::new();

// Parse the key-value pairs from the formatted string.
// See DisplayFormatType::TreeRender for details
for line in display_info.lines() {
if let Some((key, value)) = line.split_once('=') {
extra_info.insert(key.to_string(), value.to_string());
} else {
extra_info.insert(line.to_string(), "".to_string());
}
}

Expand Down
6 changes: 3 additions & 3 deletions datafusion/physical-plan/src/sorts/partial_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,11 @@ impl DisplayAs for PartialSortExec {
}
DisplayFormatType::TreeRender => match self.fetch {
Some(fetch) => {
writeln!(f, "limit={fetch}")?;
writeln!(f, "sort keys={}", self.expr)
writeln!(f, "{}", self.expr)?;
writeln!(f, "limit={fetch}")
}
None => {
writeln!(f, "sort keys={}", self.expr)
writeln!(f, "{}", self.expr)
}
},
}
Expand Down
6 changes: 3 additions & 3 deletions datafusion/physical-plan/src/sorts/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,11 +1007,11 @@ impl DisplayAs for SortExec {
}
DisplayFormatType::TreeRender => match self.fetch {
Some(fetch) => {
writeln!(f, "limit={fetch}")?;
writeln!(f, "sort keys=[{}]", self.expr)
writeln!(f, "{}", self.expr)?;
writeln!(f, "limit={fetch}")
}
None => {
writeln!(f, "sort keys=[{}]", self.expr)
writeln!(f, "{}", self.expr)
}
},
}
Expand Down
157 changes: 74 additions & 83 deletions datafusion/sqllogictest/test_files/explain_tree.slt
Original file line number Diff line number Diff line change
Expand Up @@ -674,17 +674,16 @@ physical_plan
23)┌─────────────┴─────────────┐
24)│ SortExec │
25)│ -------------------- │
26)│ sort keys: │
27)│ [v1@0 ASC NULLS LAST] │
28)└─────────────┬─────────────┘
29)┌─────────────┴─────────────┐
30)│ ProjectionExec │
31)│ -------------------- │
32)│ v1: value@0 │
33)└─────────────┬─────────────┘
34)┌─────────────┴─────────────┐
35)│ LazyMemoryExec │
36)└───────────────────────────┘
26)│ v1@0 ASC NULLS LAST │
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is very nice

27)└─────────────┬─────────────┘
28)┌─────────────┴─────────────┐
29)│ ProjectionExec │
30)│ -------------------- │
31)│ v1: value@0 │
32)└─────────────┬─────────────┘
33)┌─────────────┴─────────────┐
34)│ LazyMemoryExec │
35)└───────────────────────────┘

query TT
explain select
Expand Down Expand Up @@ -745,16 +744,14 @@ physical_plan
01)┌───────────────────────────┐
02)│ SortExec │
03)│ -------------------- │
04)│ sort keys: │
05)│ [string_col@1 ASC NULLS │
06)│ LAST] │
07)└─────────────┬─────────────┘
08)┌─────────────┴─────────────┐
09)│ DataSourceExec │
10)│ -------------------- │
11)│ files: 1 │
12)│ format: csv │
13)└───────────────────────────┘
04)│string_col@1 ASC NULLS LAST│
05)└─────────────┬─────────────┘
06)┌─────────────┴─────────────┐
07)│ DataSourceExec │
08)│ -------------------- │
09)│ files: 1 │
10)│ format: csv │
11)└───────────────────────────┘

# Query for sort with limit.
query TT
Expand All @@ -769,16 +766,14 @@ physical_plan
03)│ -------------------- │
04)│ limit: 1 │
05)│ │
06)│ sort keys: │
07)│ [string_col@1 ASC NULLS │
08)│ LAST] │
09)└─────────────┬─────────────┘
10)┌─────────────┴─────────────┐
11)│ DataSourceExec │
12)│ -------------------- │
13)│ files: 1 │
14)│ format: csv │
15)└───────────────────────────┘
06)│string_col@1 ASC NULLS LAST│
07)└─────────────┬─────────────┘
08)┌─────────────┴─────────────┐
09)│ DataSourceExec │
10)│ -------------------- │
11)│ files: 1 │
12)│ format: csv │
13)└───────────────────────────┘

# Query with projection on csv
query TT
Expand Down Expand Up @@ -865,33 +860,31 @@ physical_plan
41)┌─────────────┴─────────────┐
42)│ SortExec │
43)│ -------------------- │
44)│ sort keys: │
45)│ [int_col@0 ASC NULLS LAST]│
46)└─────────────┬─────────────┘
47)┌─────────────┴─────────────┐
48)│ BoundedWindowAggExec │
49)│ -------------------- │
50)│ mode: Sorted │
51)│ │
52)│ select_list: │
53)│ rank() ORDER BY [table1 │
54)│ .int_col DESC NULLS │
55)│ FIRST] RANGE BETWEEN │
56)│ UNBOUNDED PRECEDING AND │
57)│ CURRENT ROW │
58)└─────────────┬─────────────┘
59)┌─────────────┴─────────────┐
60)│ SortExec │
61)│ -------------------- │
62)│ sort keys: │
63)│ [int_col@0 DESC] │
64)└─────────────┬─────────────┘
65)┌─────────────┴─────────────┐
66)│ DataSourceExec │
67)│ -------------------- │
68)│ files: 1 │
69)│ format: csv │
70)└───────────────────────────┘
44)│ int_col@0 ASC NULLS LAST │
45)└─────────────┬─────────────┘
46)┌─────────────┴─────────────┐
47)│ BoundedWindowAggExec │
48)│ -------------------- │
49)│ mode: Sorted │
50)│ │
51)│ select_list: │
52)│ rank() ORDER BY [table1 │
53)│ .int_col DESC NULLS │
54)│ FIRST] RANGE BETWEEN │
55)│ UNBOUNDED PRECEDING AND │
56)│ CURRENT ROW │
57)└─────────────┬─────────────┘
58)┌─────────────┴─────────────┐
59)│ SortExec │
60)│ -------------------- │
61)│ int_col@0 DESC │
62)└─────────────┬─────────────┘
63)┌─────────────┴─────────────┐
64)│ DataSourceExec │
65)│ -------------------- │
66)│ files: 1 │
67)│ format: csv │
68)└───────────────────────────┘

# Query with projection on parquet
query TT
Expand Down Expand Up @@ -1025,17 +1018,16 @@ physical_plan
01)┌───────────────────────────┐
02)│ PartialSortExec │
03)│ -------------------- │
04)│ sort keys: │
05)│ a@1 ASC NULLS LAST, b@2 │
06)│ ASC NULLS LAST, d@4 │
07)│ ASC NULLS LAST │
08)└─────────────┬─────────────┘
09)┌─────────────┴─────────────┐
10)│ StreamingTableExec │
11)│ -------------------- │
12)│ infinite: true │
13)│ limit: None │
14)└───────────────────────────┘
04)│ a@1 ASC NULLS LAST, b@2 │
05)│ ASC NULLS LAST, d@4 │
06)│ ASC NULLS LAST │
07)└─────────────┬─────────────┘
08)┌─────────────┴─────────────┐
09)│ StreamingTableExec │
10)│ -------------------- │
11)│ infinite: true │
12)│ limit: None │
13)└───────────────────────────┘

query TT
EXPLAIN SELECT *
Expand All @@ -1050,19 +1042,18 @@ physical_plan
01)┌───────────────────────────┐
02)│ PartialSortExec │
03)│ -------------------- │
04)│ limit: 50 │
05)│ │
06)│ sort keys: │
07)│ a@1 ASC NULLS LAST, b@2 │
08)│ ASC NULLS LAST, d@4 │
09)│ ASC NULLS LAST │
10)└─────────────┬─────────────┘
11)┌─────────────┴─────────────┐
12)│ StreamingTableExec │
13)│ -------------------- │
14)│ infinite: true │
15)│ limit: None │
16)└───────────────────────────┘
04)│ a@1 ASC NULLS LAST, b@2 │
05)│ ASC NULLS LAST, d@4 │
06)│ ASC NULLS LAST │
07)│ │
08)│ limit: 50 │
09)└─────────────┬─────────────┘
10)┌─────────────┴─────────────┐
11)│ StreamingTableExec │
12)│ -------------------- │
13)│ infinite: true │
14)│ limit: None │
15)└───────────────────────────┘

# Query with hash join.
query TT
Expand Down Expand Up @@ -1270,7 +1261,7 @@ physical_plan
06)┌─────────────┴─────────────┐┌─────────────┴─────────────┐
07)│ SortExec ││ SortExec │
08)│ -------------------- ││ -------------------- │
09)│ sort keys: [c1@0 ASC] ││ sort keys: [c1@0 ASC]
09)│ c1@0 ASC ││ c1@0 ASC
10)└─────────────┬─────────────┘└─────────────┬─────────────┘
11)┌─────────────┴─────────────┐┌─────────────┴─────────────┐
12)│ DataSourceExec ││ DataSourceExec │
Expand Down