This is an automated email from the ASF dual-hosted git repository.
ytyou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new f0b86fc041 Implement `tree` explain for `BoundedWindowAggExec` and
`WindowAggExec` (#15084)
f0b86fc041 is described below
commit f0b86fc04103621bc12954214df4a89287761a3f
Author: irenjj <[email protected]>
AuthorDate: Mon Mar 10 18:29:24 2025 +0800
Implement `tree` explain for `BoundedWindowAggExec` and `WindowAggExec`
(#15084)
* Implement `tree explain for `BoundedWindowAggExec` and `WindowAggExec`
* fix clippy
* add bounded win agg test
* add test
* remove
* merge
---------
Co-authored-by: Andrew Lamb <[email protected]>
---
.../src/windows/bounded_window_agg_exec.rs | 11 +-
.../physical-plan/src/windows/window_agg_exec.rs | 8 +-
.../sqllogictest/test_files/explain_tree.slt | 218 +++++++++++++++++++++
3 files changed, 233 insertions(+), 4 deletions(-)
diff --git a/datafusion/physical-plan/src/windows/bounded_window_agg_exec.rs
b/datafusion/physical-plan/src/windows/bounded_window_agg_exec.rs
index 7e37156a13..f9f4b78686 100644
--- a/datafusion/physical-plan/src/windows/bounded_window_agg_exec.rs
+++ b/datafusion/physical-plan/src/windows/bounded_window_agg_exec.rs
@@ -253,8 +253,15 @@ impl DisplayAs for BoundedWindowAggExec {
write!(f, "wdw=[{}], mode=[{:?}]", g.join(", "), mode)?;
}
DisplayFormatType::TreeRender => {
- // TODO: collect info
- write!(f, "")?;
+ let g: Vec<String> = self
+ .window_expr
+ .iter()
+ .map(|e| e.name().to_owned().to_string())
+ .collect();
+ writeln!(f, "select_list={}", g.join(", "))?;
+
+ let mode = &self.input_order_mode;
+ writeln!(f, "mode={:?}", mode)?;
}
}
Ok(())
diff --git a/datafusion/physical-plan/src/windows/window_agg_exec.rs
b/datafusion/physical-plan/src/windows/window_agg_exec.rs
index cd171115b6..3c42d3032e 100644
--- a/datafusion/physical-plan/src/windows/window_agg_exec.rs
+++ b/datafusion/physical-plan/src/windows/window_agg_exec.rs
@@ -182,8 +182,12 @@ impl DisplayAs for WindowAggExec {
write!(f, "wdw=[{}]", g.join(", "))?;
}
DisplayFormatType::TreeRender => {
- // TODO: collect info
- write!(f, "")?;
+ let g: Vec<String> = self
+ .window_expr
+ .iter()
+ .map(|e| e.name().to_owned().to_string())
+ .collect();
+ writeln!(f, "select_list={}", g.join(", "))?;
}
}
Ok(())
diff --git a/datafusion/sqllogictest/test_files/explain_tree.slt
b/datafusion/sqllogictest/test_files/explain_tree.slt
index e0459b6da2..689816ff1f 100644
--- a/datafusion/sqllogictest/test_files/explain_tree.slt
+++ b/datafusion/sqllogictest/test_files/explain_tree.slt
@@ -577,6 +577,142 @@ physical_plan
17)│ format: arrow │
18)└───────────────────────────┘
+
+# Query with window agg.
+query TT
+explain select count(*) over() from table1;
+----
+logical_plan
+01)Projection: count(Int64(1)) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
FOLLOWING AS count(*) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+02)--WindowAggr: windowExpr=[[count(Int64(1)) ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING]]
+03)----TableScan: table1 projection=[]
+physical_plan
+01)┌───────────────────────────┐
+02)│ ProjectionExec │
+03)│ -------------------- │
+04)│ count(*) ROWS BETWEEN │
+05)│ UNBOUNDED PRECEDING │
+06)│ AND UNBOUNDED FOLLOWING: │
+07)│ count(Int64(1)) ROWS │
+08)│ BETWEEN UNBOUNDED │
+09)│ PRECEDING AND UNBOUNDED │
+10)│ FOLLOWING@0 │
+11)└─────────────┬─────────────┘
+12)┌─────────────┴─────────────┐
+13)│ WindowAggExec │
+14)│ -------------------- │
+15)│ select_list: │
+16)│ count(Int64(1)) ROWS │
+17)│ BETWEEN UNBOUNDED │
+18)│ PRECEDING AND UNBOUNDED │
+19)│ FOLLOWING │
+20)└─────────────┬─────────────┘
+21)┌─────────────┴─────────────┐
+22)│ DataSourceExec │
+23)│ -------------------- │
+24)│ files: 1 │
+25)│ format: csv │
+26)└───────────────────────────┘
+
+# Query with bounded window agg.
+query TT
+explain SELECT
+ v1,
+ SUM(v1) OVER (ORDER BY v1 ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS
rolling_sum
+FROM generate_series(1, 1000) AS t1(v1);
+----
+logical_plan
+01)Projection: t1.v1, sum(t1.v1) ORDER BY [t1.v1 ASC NULLS LAST] ROWS BETWEEN
1 PRECEDING AND CURRENT ROW AS rolling_sum
+02)--WindowAggr: windowExpr=[[sum(t1.v1) ORDER BY [t1.v1 ASC NULLS LAST] ROWS
BETWEEN 1 PRECEDING AND CURRENT ROW]]
+03)----SubqueryAlias: t1
+04)------Projection: tmp_table.value AS v1
+05)--------TableScan: tmp_table projection=[value]
+physical_plan
+01)┌───────────────────────────┐
+02)│ ProjectionExec │
+03)│ -------------------- │
+04)│ rolling_sum: │
+05)│ sum(t1.v1) ORDER BY [t1.v1│
+06)│ ASC NULLS LAST] ROWS │
+07)│ BETWEEN 1 PRECEDING │
+08)│ AND CURRENT ROW@1 │
+09)│ │
+10)│ v1: v1@0 │
+11)└─────────────┬─────────────┘
+12)┌─────────────┴─────────────┐
+13)│ BoundedWindowAggExec │
+14)│ -------------------- │
+15)│ mode: Sorted │
+16)│ │
+17)│ select_list: │
+18)│ sum(t1.v1) ORDER BY [t1.v1│
+19)│ ASC NULLS LAST] ROWS │
+20)│ BETWEEN 1 PRECEDING │
+21)│ AND CURRENT ROW │
+22)└─────────────┬─────────────┘
+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)└───────────────────────────┘
+
+query TT
+explain select
+ count(*) over(),
+ row_number() over ()
+from table1
+----
+logical_plan
+01)Projection: count(Int64(1)) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
FOLLOWING AS count(*) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,
row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+02)--WindowAggr: windowExpr=[[count(Int64(1)) ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING, row_number() ROWS BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING]]
+03)----TableScan: table1 projection=[]
+physical_plan
+01)┌───────────────────────────┐
+02)│ ProjectionExec │
+03)│ -------------------- │
+04)│ count(*) ROWS BETWEEN │
+05)│ UNBOUNDED PRECEDING │
+06)│ AND UNBOUNDED FOLLOWING: │
+07)│ count(Int64(1)) ROWS │
+08)│ BETWEEN UNBOUNDED │
+09)│ PRECEDING AND UNBOUNDED │
+10)│ FOLLOWING@0 │
+11)│ │
+12)│ row_number() ROWS BETWEEN │
+13)│ UNBOUNDED PRECEDING AND │
+14)│ UNBOUNDED FOLLOWING: │
+15)│ row_number() ROWS BETWEEN │
+16)│ UNBOUNDED PRECEDING AND │
+17)│ UNBOUNDED FOLLOWING@1 │
+18)└─────────────┬─────────────┘
+19)┌─────────────┴─────────────┐
+20)│ WindowAggExec │
+21)│ -------------------- │
+22)│ select_list: │
+23)│ count(Int64(1)) ROWS │
+24)│ BETWEEN UNBOUNDED │
+25)│ PRECEDING AND UNBOUNDED │
+26)│ FOLLOWING, row_number() │
+27)│ ROWS BETWEEN UNBOUNDED │
+28)│ PRECEDING AND UNBOUNDED │
+29)│ FOLLOWING │
+30)└─────────────┬─────────────┘
+31)┌─────────────┴─────────────┐
+32)│ DataSourceExec │
+33)│ -------------------- │
+34)│ files: 1 │
+35)│ format: csv │
+36)└───────────────────────────┘
+
# Query for sort.
query TT
explain SELECT * FROM table1 ORDER BY string_col;
@@ -653,6 +789,88 @@ physical_plan
20)│ format: csv │
21)└───────────────────────────┘
+query TT
+explain select
+ rank() over(ORDER BY int_col DESC),
+ row_number() over (ORDER BY int_col ASC)
+from table1
+----
+logical_plan
+01)Projection: rank() ORDER BY [table1.int_col DESC NULLS FIRST] RANGE BETWEEN
UNBOUNDED PRECEDING AND CURRENT ROW, row_number() ORDER BY [table1.int_col ASC
NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+02)--WindowAggr: windowExpr=[[row_number() ORDER BY [table1.int_col ASC NULLS
LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
+03)----WindowAggr: windowExpr=[[rank() ORDER BY [table1.int_col DESC NULLS
FIRST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
+04)------TableScan: table1 projection=[int_col]
+physical_plan
+01)┌───────────────────────────┐
+02)│ ProjectionExec │
+03)│ -------------------- │
+04)│ rank() ORDER BY [table1 │
+05)│ .int_col DESC NULLS │
+06)│ FIRST] RANGE BETWEEN │
+07)│ UNBOUNDED PRECEDING AND │
+08)│ CURRENT ROW: │
+09)│ rank() ORDER BY [table1 │
+10)│ .int_col DESC NULLS │
+11)│ FIRST] RANGE BETWEEN │
+12)│ UNBOUNDED PRECEDING AND │
+13)│ CURRENT ROW@1 │
+14)│ │
+15)│ row_number() ORDER BY │
+16)│ [table1.int_col ASC │
+17)│ NULLS LAST] RANGE │
+18)│ BETWEEN UNBOUNDED │
+19)│ PRECEDING AND CURRENT │
+20)│ ROW: │
+21)│ row_number() ORDER BY │
+22)│ [table1.int_col ASC │
+23)│ NULLS LAST] RANGE │
+24)│ BETWEEN UNBOUNDED │
+25)│ PRECEDING AND CURRENT │
+26)│ ROW@2 │
+27)└─────────────┬─────────────┘
+28)┌─────────────┴─────────────┐
+29)│ BoundedWindowAggExec │
+30)│ -------------------- │
+31)│ mode: Sorted │
+32)│ │
+33)│ select_list: │
+34)│ row_number() ORDER BY │
+35)│ [table1.int_col ASC │
+36)│ NULLS LAST] RANGE │
+37)│ BETWEEN UNBOUNDED │
+38)│ PRECEDING AND CURRENT │
+39)│ ROW │
+40)└─────────────┬─────────────┘
+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)└───────────────────────────┘
# Query with projection on parquet
query TT
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]