From bb8b997e5a8b6479c74127bf78ad20563dd78374 Mon Sep 17 00:00:00 2001 From: Alan Tang Date: Tue, 11 Mar 2025 09:34:00 +0800 Subject: [PATCH 1/3] feat: implement tree rendering for RepartitionExec Signed-off-by: Alan Tang --- .../physical-plan/src/repartition/mod.rs | 15 +- .../sqllogictest/test_files/explain_tree.slt | 694 +++++++++++------- 2 files changed, 452 insertions(+), 257 deletions(-) diff --git a/datafusion/physical-plan/src/repartition/mod.rs b/datafusion/physical-plan/src/repartition/mod.rs index e9a360c2ece3..19d789c96f7b 100644 --- a/datafusion/physical-plan/src/repartition/mod.rs +++ b/datafusion/physical-plan/src/repartition/mod.rs @@ -507,8 +507,19 @@ impl DisplayAs for RepartitionExec { Ok(()) } DisplayFormatType::TreeRender => { - // TODO: collect info - write!(f, "") + writeln!(f, "partitioning_scheme={}", self.partitioning(),)?; + writeln!( + f, + "output_partition_count={}", + self.input.output_partitioning().partition_count() + )?; + if self.preserve_order { + writeln!(f, ", preserve_order={}", "SortPreserving")?; + } + if let Some(sort_exprs) = self.sort_exprs() { + write!(f, "sort_exprs={}", sort_exprs.clone())?; + } + Ok(()) } } } diff --git a/datafusion/sqllogictest/test_files/explain_tree.slt b/datafusion/sqllogictest/test_files/explain_tree.slt index be926c0fc9c0..bc4a033ab728 100644 --- a/datafusion/sqllogictest/test_files/explain_tree.slt +++ b/datafusion/sqllogictest/test_files/explain_tree.slt @@ -155,13 +155,19 @@ physical_plan 09)└─────────────┬─────────────┘ 10)┌─────────────┴─────────────┐ 11)│ RepartitionExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ DataSourceExec │ -15)│ -------------------- │ -16)│ files: 1 │ -17)│ format: csv │ -18)└───────────────────────────┘ +12)│ -------------------- │ +13)│ output_partition_count: │ +14)│ 1 │ +15)│ │ +16)│ partitioning_scheme: │ +17)│ RoundRobinBatch(4) │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ DataSourceExec │ +21)│ -------------------- │ +22)│ files: 1 │ +23)│ format: csv │ +24)└───────────────────────────┘ # Aggregate query TT @@ -179,19 +185,31 @@ physical_plan 06)└─────────────┬─────────────┘ 07)┌─────────────┴─────────────┐ 08)│ RepartitionExec │ -09)└─────────────┬─────────────┘ -10)┌─────────────┴─────────────┐ -11)│ AggregateExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ RepartitionExec │ +09)│ -------------------- │ +10)│ output_partition_count: │ +11)│ 4 │ +12)│ │ +13)│ partitioning_scheme: │ +14)│ Hash([string_col@0], 4) │ 15)└─────────────┬─────────────┘ 16)┌─────────────┴─────────────┐ -17)│ DataSourceExec │ -18)│ -------------------- │ -19)│ files: 1 │ -20)│ format: csv │ -21)└───────────────────────────┘ +17)│ AggregateExec │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ RepartitionExec │ +21)│ -------------------- │ +22)│ output_partition_count: │ +23)│ 1 │ +24)│ │ +25)│ partitioning_scheme: │ +26)│ RoundRobinBatch(4) │ +27)└─────────────┬─────────────┘ +28)┌─────────────┴─────────────┐ +29)│ DataSourceExec │ +30)│ -------------------- │ +31)│ files: 1 │ +32)│ format: csv │ +33)└───────────────────────────┘ # Limit query TT @@ -238,16 +256,28 @@ physical_plan 12)└─────────────┬─────────────┘└─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ 14)│ RepartitionExec ││ RepartitionExec │ -15)└─────────────┬─────────────┘└─────────────┬─────────────┘ -16)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -17)│ RepartitionExec ││ RepartitionExec │ -18)└─────────────┬─────────────┘└─────────────┬─────────────┘ -19)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -20)│ DataSourceExec ││ DataSourceExec │ -21)│ -------------------- ││ -------------------- │ -22)│ files: 1 ││ files: 1 │ -23)│ format: csv ││ format: parquet │ -24)└───────────────────────────┘└───────────────────────────┘ +15)│ -------------------- ││ -------------------- │ +16)│ output_partition_count: ││ output_partition_count: │ +17)│ 4 ││ 4 │ +18)│ ││ │ +19)│ partitioning_scheme: ││ partitioning_scheme: │ +20)│ Hash([int_col@0], 4) ││ Hash([int_col@0], 4) │ +21)└─────────────┬─────────────┘└─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +23)│ RepartitionExec ││ RepartitionExec │ +24)│ -------------------- ││ -------------------- │ +25)│ output_partition_count: ││ output_partition_count: │ +26)│ 1 ││ 1 │ +27)│ ││ │ +28)│ partitioning_scheme: ││ partitioning_scheme: │ +29)│ RoundRobinBatch(4) ││ RoundRobinBatch(4) │ +30)└─────────────┬─────────────┘└─────────────┬─────────────┘ +31)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +32)│ DataSourceExec ││ DataSourceExec │ +33)│ -------------------- ││ -------------------- │ +34)│ files: 1 ││ files: 1 │ +35)│ format: csv ││ format: parquet │ +36)└───────────────────────────┘└───────────────────────────┘ # 3 Joins query TT @@ -282,29 +312,44 @@ physical_plan 12)└─────────────┬─────────────┘ └─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐ ┌─────────────┴─────────────┐ 14)│ HashJoinExec │ │ RepartitionExec │ -15)│ -------------------- │ │ │ -16)│ on: ├──────────────┐ │ │ -17)│ (int_col@0 = int_col@0) │ │ │ │ -18)└─────────────┬─────────────┘ │ └─────────────┬─────────────┘ -19)┌─────────────┴─────────────┐┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -20)│ CoalesceBatchesExec ││ CoalesceBatchesExec ││ DataSourceExec │ -21)│ ││ ││ -------------------- │ -22)│ ││ ││ bytes: 1560 │ -23)│ ││ ││ format: memory │ -24)│ ││ ││ rows: 1 │ -25)└─────────────┬─────────────┘└─────────────┬─────────────┘└───────────────────────────┘ -26)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -27)│ RepartitionExec ││ RepartitionExec │ -28)└─────────────┬─────────────┘└─────────────┬─────────────┘ +15)│ -------------------- │ │ -------------------- │ +16)│ on: │ │ output_partition_count: │ +17)│ (int_col@0 = int_col@0) ├──────────────┐ │ 1 │ +18)│ │ │ │ │ +19)│ │ │ │ partitioning_scheme: │ +20)│ │ │ │ Hash([int_col@0], 4) │ +21)└─────────────┬─────────────┘ │ └─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +23)│ CoalesceBatchesExec ││ CoalesceBatchesExec ││ DataSourceExec │ +24)│ ││ ││ -------------------- │ +25)│ ││ ││ bytes: 1560 │ +26)│ ││ ││ format: memory │ +27)│ ││ ││ rows: 1 │ +28)└─────────────┬─────────────┘└─────────────┬─────────────┘└───────────────────────────┘ 29)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ 30)│ RepartitionExec ││ RepartitionExec │ -31)└─────────────┬─────────────┘└─────────────┬─────────────┘ -32)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -33)│ DataSourceExec ││ DataSourceExec │ -34)│ -------------------- ││ -------------------- │ -35)│ files: 1 ││ files: 1 │ -36)│ format: csv ││ format: parquet │ -37)└───────────────────────────┘└───────────────────────────┘ +31)│ -------------------- ││ -------------------- │ +32)│ output_partition_count: ││ output_partition_count: │ +33)│ 4 ││ 4 │ +34)│ ││ │ +35)│ partitioning_scheme: ││ partitioning_scheme: │ +36)│ Hash([int_col@0], 4) ││ Hash([int_col@0], 4) │ +37)└─────────────┬─────────────┘└─────────────┬─────────────┘ +38)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +39)│ RepartitionExec ││ RepartitionExec │ +40)│ -------------------- ││ -------------------- │ +41)│ output_partition_count: ││ output_partition_count: │ +42)│ 1 ││ 1 │ +43)│ ││ │ +44)│ partitioning_scheme: ││ partitioning_scheme: │ +45)│ RoundRobinBatch(4) ││ RoundRobinBatch(4) │ +46)└─────────────┬─────────────┘└─────────────┬─────────────┘ +47)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +48)│ DataSourceExec ││ DataSourceExec │ +49)│ -------------------- ││ -------------------- │ +50)│ files: 1 ││ files: 1 │ +51)│ format: csv ││ format: parquet │ +52)└───────────────────────────┘└───────────────────────────┘ # Long Filter (demonstrate what happens with wrapping) query TT @@ -332,13 +377,19 @@ physical_plan 13)└─────────────┬─────────────┘ 14)┌─────────────┴─────────────┐ 15)│ RepartitionExec │ -16)└─────────────┬─────────────┘ -17)┌─────────────┴─────────────┐ -18)│ DataSourceExec │ -19)│ -------------------- │ -20)│ files: 1 │ -21)│ format: csv │ -22)└───────────────────────────┘ +16)│ -------------------- │ +17)│ output_partition_count: │ +18)│ 1 │ +19)│ │ +20)│ partitioning_scheme: │ +21)│ RoundRobinBatch(4) │ +22)└─────────────┬─────────────┘ +23)┌─────────────┴─────────────┐ +24)│ DataSourceExec │ +25)│ -------------------- │ +26)│ files: 1 │ +27)│ format: csv │ +28)└───────────────────────────┘ # Check maximum line limit. query TT @@ -389,13 +440,19 @@ physical_plan 37)└─────────────┬─────────────┘ 38)┌─────────────┴─────────────┐ 39)│ RepartitionExec │ -40)└─────────────┬─────────────┘ -41)┌─────────────┴─────────────┐ -42)│ DataSourceExec │ -43)│ -------------------- │ -44)│ files: 1 │ -45)│ format: csv │ -46)└───────────────────────────┘ +40)│ -------------------- │ +41)│ output_partition_count: │ +42)│ 1 │ +43)│ │ +44)│ partitioning_scheme: │ +45)│ RoundRobinBatch(4) │ +46)└─────────────┬─────────────┘ +47)┌─────────────┴─────────────┐ +48)│ DataSourceExec │ +49)│ -------------------- │ +50)│ files: 1 │ +51)│ format: csv │ +52)└───────────────────────────┘ # Check exactly the render width. query TT @@ -418,13 +475,19 @@ physical_plan 09)└─────────────┬─────────────┘ 10)┌─────────────┴─────────────┐ 11)│ RepartitionExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ DataSourceExec │ -15)│ -------------------- │ -16)│ files: 1 │ -17)│ format: csv │ -18)└───────────────────────────┘ +12)│ -------------------- │ +13)│ output_partition_count: │ +14)│ 1 │ +15)│ │ +16)│ partitioning_scheme: │ +17)│ RoundRobinBatch(4) │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ DataSourceExec │ +21)│ -------------------- │ +22)│ files: 1 │ +23)│ format: csv │ +24)└───────────────────────────┘ # Check with the render witdth + 1. query TT @@ -448,13 +511,19 @@ physical_plan 10)└─────────────┬─────────────┘ 11)┌─────────────┴─────────────┐ 12)│ RepartitionExec │ -13)└─────────────┬─────────────┘ -14)┌─────────────┴─────────────┐ -15)│ DataSourceExec │ -16)│ -------------------- │ -17)│ files: 1 │ -18)│ format: csv │ -19)└───────────────────────────┘ +13)│ -------------------- │ +14)│ output_partition_count: │ +15)│ 1 │ +16)│ │ +17)│ partitioning_scheme: │ +18)│ RoundRobinBatch(4) │ +19)└─────────────┬─────────────┘ +20)┌─────────────┴─────────────┐ +21)│ DataSourceExec │ +22)│ -------------------- │ +23)│ files: 1 │ +24)│ format: csv │ +25)└───────────────────────────┘ # Query with filter on csv query TT @@ -476,13 +545,19 @@ physical_plan 09)└─────────────┬─────────────┘ 10)┌─────────────┴─────────────┐ 11)│ RepartitionExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ DataSourceExec │ -15)│ -------------------- │ -16)│ files: 1 │ -17)│ format: csv │ -18)└───────────────────────────┘ +12)│ -------------------- │ +13)│ output_partition_count: │ +14)│ 1 │ +15)│ │ +16)│ partitioning_scheme: │ +17)│ RoundRobinBatch(4) │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ DataSourceExec │ +21)│ -------------------- │ +22)│ files: 1 │ +23)│ format: csv │ +24)└───────────────────────────┘ # Query with filter on parquet @@ -505,16 +580,22 @@ physical_plan 09)└─────────────┬─────────────┘ 10)┌─────────────┴─────────────┐ 11)│ RepartitionExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ DataSourceExec │ -15)│ -------------------- │ -16)│ files: 1 │ -17)│ format: parquet │ -18)│ │ -19)│ predicate: │ -20)│ string_col@1 != foo │ -21)└───────────────────────────┘ +12)│ -------------------- │ +13)│ output_partition_count: │ +14)│ 1 │ +15)│ │ +16)│ partitioning_scheme: │ +17)│ RoundRobinBatch(4) │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ DataSourceExec │ +21)│ -------------------- │ +22)│ files: 1 │ +23)│ format: parquet │ +24)│ │ +25)│ predicate: │ +26)│ string_col@1 != foo │ +27)└───────────────────────────┘ # Query with filter on memory query TT @@ -562,13 +643,19 @@ physical_plan 09)└─────────────┬─────────────┘ 10)┌─────────────┴─────────────┐ 11)│ RepartitionExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ DataSourceExec │ -15)│ -------------------- │ -16)│ files: 1 │ -17)│ format: json │ -18)└───────────────────────────┘ +12)│ -------------------- │ +13)│ output_partition_count: │ +14)│ 1 │ +15)│ │ +16)│ partitioning_scheme: │ +17)│ RoundRobinBatch(4) │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ DataSourceExec │ +21)│ -------------------- │ +22)│ files: 1 │ +23)│ format: json │ +24)└───────────────────────────┘ # Query with filter on arrow query TT @@ -590,13 +677,19 @@ physical_plan 09)└─────────────┬─────────────┘ 10)┌─────────────┴─────────────┐ 11)│ RepartitionExec │ -12)└─────────────┬─────────────┘ -13)┌─────────────┴─────────────┐ -14)│ DataSourceExec │ -15)│ -------------------- │ -16)│ files: 1 │ -17)│ format: arrow │ -18)└───────────────────────────┘ +12)│ -------------------- │ +13)│ output_partition_count: │ +14)│ 1 │ +15)│ │ +16)│ partitioning_scheme: │ +17)│ RoundRobinBatch(4) │ +18)└─────────────┬─────────────┘ +19)┌─────────────┴─────────────┐ +20)│ DataSourceExec │ +21)│ -------------------- │ +22)│ files: 1 │ +23)│ format: arrow │ +24)└───────────────────────────┘ # Query with window agg. @@ -797,13 +890,19 @@ physical_plan 12)└─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐ 14)│ RepartitionExec │ -15)└─────────────┬─────────────┘ -16)┌─────────────┴─────────────┐ -17)│ DataSourceExec │ -18)│ -------------------- │ -19)│ files: 1 │ -20)│ format: csv │ -21)└───────────────────────────┘ +15)│ -------------------- │ +16)│ output_partition_count: │ +17)│ 1 │ +18)│ │ +19)│ partitioning_scheme: │ +20)│ RoundRobinBatch(4) │ +21)└─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐ +23)│ DataSourceExec │ +24)│ -------------------- │ +25)│ files: 1 │ +26)│ format: csv │ +27)└───────────────────────────┘ query TT explain select @@ -908,13 +1007,19 @@ physical_plan 12)└─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐ 14)│ RepartitionExec │ -15)└─────────────┬─────────────┘ -16)┌─────────────┴─────────────┐ -17)│ DataSourceExec │ -18)│ -------------------- │ -19)│ files: 1 │ -20)│ format: parquet │ -21)└───────────────────────────┘ +15)│ -------------------- │ +16)│ output_partition_count: │ +17)│ 1 │ +18)│ │ +19)│ partitioning_scheme: │ +20)│ RoundRobinBatch(4) │ +21)└─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐ +23)│ DataSourceExec │ +24)│ -------------------- │ +25)│ files: 1 │ +26)│ format: parquet │ +27)└───────────────────────────┘ # Query with projection on memory @@ -966,13 +1071,19 @@ physical_plan 11)└─────────────┬─────────────┘ 12)┌─────────────┴─────────────┐ 13)│ RepartitionExec │ -14)└─────────────┬─────────────┘ -15)┌─────────────┴─────────────┐ -16)│ DataSourceExec │ -17)│ -------------------- │ -18)│ files: 1 │ -19)│ format: json │ -20)└───────────────────────────┘ +14)│ -------------------- │ +15)│ output_partition_count: │ +16)│ 1 │ +17)│ │ +18)│ partitioning_scheme: │ +19)│ RoundRobinBatch(4) │ +20)└─────────────┬─────────────┘ +21)┌─────────────┴─────────────┐ +22)│ DataSourceExec │ +23)│ -------------------- │ +24)│ files: 1 │ +25)│ format: json │ +26)└───────────────────────────┘ # Query with projection on arrow @@ -997,13 +1108,19 @@ physical_plan 12)└─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐ 14)│ RepartitionExec │ -15)└─────────────┬─────────────┘ -16)┌─────────────┴─────────────┐ -17)│ DataSourceExec │ -18)│ -------------------- │ -19)│ files: 1 │ -20)│ format: arrow │ -21)└───────────────────────────┘ +15)│ -------------------- │ +16)│ output_partition_count: │ +17)│ 1 │ +18)│ │ +19)│ partitioning_scheme: │ +20)│ RoundRobinBatch(4) │ +21)└─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐ +23)│ DataSourceExec │ +24)│ -------------------- │ +25)│ files: 1 │ +26)│ format: arrow │ +27)└───────────────────────────┘ # Query with PartialSortExec. query TT @@ -1081,36 +1198,47 @@ physical_plan 15)└─────────────┬─────────────┘└─────────────┬─────────────┘ 16)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ 17)│ RepartitionExec ││ RepartitionExec │ -18)└─────────────┬─────────────┘└─────────────┬─────────────┘ -19)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -20)│ ProjectionExec ││ RepartitionExec │ -21)│ -------------------- ││ │ -22)│ CAST(table1.string_col AS ││ │ -23)│ Utf8View): ││ │ -24)│ CAST(string_col@1 AS ││ │ -25)│ Utf8View) ││ │ -26)│ ││ │ -27)│ bigint_col: ││ │ -28)│ bigint_col@2 ││ │ -29)│ ││ │ -30)│ date_col: date_col@3 ││ │ -31)│ int_col: int_col@0 ││ │ -32)│ ││ │ -33)│ string_col: ││ │ -34)│ string_col@1 ││ │ -35)└─────────────┬─────────────┘└─────────────┬─────────────┘ -36)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -37)│ RepartitionExec ││ DataSourceExec │ -38)│ ││ -------------------- │ -39)│ ││ files: 1 │ -40)│ ││ format: parquet │ -41)└─────────────┬─────────────┘└───────────────────────────┘ -42)┌─────────────┴─────────────┐ -43)│ DataSourceExec │ -44)│ -------------------- │ -45)│ files: 1 │ -46)│ format: csv │ -47)└───────────────────────────┘ +18)│ -------------------- ││ -------------------- │ +19)│ output_partition_count: ││ output_partition_count: │ +20)│ 4 ││ 4 │ +21)│ ││ │ +22)│ partitioning_scheme: ││ partitioning_scheme: │ +23)│ Hash([int_col@0, CAST ││ Hash([int_col@0, │ +24)│ (table1.string_col ││ string_col@1], │ +25)│ AS Utf8View)@4], 4) ││ 4) │ +26)└─────────────┬─────────────┘└─────────────┬─────────────┘ +27)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +28)│ ProjectionExec ││ RepartitionExec │ +29)│ -------------------- ││ -------------------- │ +30)│ CAST(table1.string_col AS ││ output_partition_count: │ +31)│ Utf8View): ││ 1 │ +32)│ CAST(string_col@1 AS ││ │ +33)│ Utf8View) ││ partitioning_scheme: │ +34)│ ││ RoundRobinBatch(4) │ +35)│ bigint_col: ││ │ +36)│ bigint_col@2 ││ │ +37)│ ││ │ +38)│ date_col: date_col@3 ││ │ +39)│ int_col: int_col@0 ││ │ +40)│ ││ │ +41)│ string_col: ││ │ +42)│ string_col@1 ││ │ +43)└─────────────┬─────────────┘└─────────────┬─────────────┘ +44)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +45)│ RepartitionExec ││ DataSourceExec │ +46)│ -------------------- ││ -------------------- │ +47)│ output_partition_count: ││ files: 1 │ +48)│ 1 ││ format: parquet │ +49)│ ││ │ +50)│ partitioning_scheme: ││ │ +51)│ RoundRobinBatch(4) ││ │ +52)└─────────────┬─────────────┘└───────────────────────────┘ +53)┌─────────────┴─────────────┐ +54)│ DataSourceExec │ +55)│ -------------------- │ +56)│ files: 1 │ +57)│ format: csv │ +58)└───────────────────────────┘ # Query with outer hash join. query TT @@ -1140,36 +1268,47 @@ physical_plan 17)└─────────────┬─────────────┘└─────────────┬─────────────┘ 18)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ 19)│ RepartitionExec ││ RepartitionExec │ -20)└─────────────┬─────────────┘└─────────────┬─────────────┘ -21)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -22)│ ProjectionExec ││ RepartitionExec │ -23)│ -------------------- ││ │ -24)│ CAST(table1.string_col AS ││ │ -25)│ Utf8View): ││ │ -26)│ CAST(string_col@1 AS ││ │ -27)│ Utf8View) ││ │ -28)│ ││ │ -29)│ bigint_col: ││ │ -30)│ bigint_col@2 ││ │ -31)│ ││ │ -32)│ date_col: date_col@3 ││ │ -33)│ int_col: int_col@0 ││ │ -34)│ ││ │ -35)│ string_col: ││ │ -36)│ string_col@1 ││ │ -37)└─────────────┬─────────────┘└─────────────┬─────────────┘ -38)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ -39)│ RepartitionExec ││ DataSourceExec │ -40)│ ││ -------------------- │ -41)│ ││ files: 1 │ -42)│ ││ format: parquet │ -43)└─────────────┬─────────────┘└───────────────────────────┘ -44)┌─────────────┴─────────────┐ -45)│ DataSourceExec │ -46)│ -------------------- │ -47)│ files: 1 │ -48)│ format: csv │ -49)└───────────────────────────┘ +20)│ -------------------- ││ -------------------- │ +21)│ output_partition_count: ││ output_partition_count: │ +22)│ 4 ││ 4 │ +23)│ ││ │ +24)│ partitioning_scheme: ││ partitioning_scheme: │ +25)│ Hash([int_col@0, CAST ││ Hash([int_col@0, │ +26)│ (table1.string_col ││ string_col@1], │ +27)│ AS Utf8View)@4], 4) ││ 4) │ +28)└─────────────┬─────────────┘└─────────────┬─────────────┘ +29)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +30)│ ProjectionExec ││ RepartitionExec │ +31)│ -------------------- ││ -------------------- │ +32)│ CAST(table1.string_col AS ││ output_partition_count: │ +33)│ Utf8View): ││ 1 │ +34)│ CAST(string_col@1 AS ││ │ +35)│ Utf8View) ││ partitioning_scheme: │ +36)│ ││ RoundRobinBatch(4) │ +37)│ bigint_col: ││ │ +38)│ bigint_col@2 ││ │ +39)│ ││ │ +40)│ date_col: date_col@3 ││ │ +41)│ int_col: int_col@0 ││ │ +42)│ ││ │ +43)│ string_col: ││ │ +44)│ string_col@1 ││ │ +45)└─────────────┬─────────────┘└─────────────┬─────────────┘ +46)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +47)│ RepartitionExec ││ DataSourceExec │ +48)│ -------------------- ││ -------------------- │ +49)│ output_partition_count: ││ files: 1 │ +50)│ 1 ││ format: parquet │ +51)│ ││ │ +52)│ partitioning_scheme: ││ │ +53)│ RoundRobinBatch(4) ││ │ +54)└─────────────┬─────────────┘└───────────────────────────┘ +55)┌─────────────┴─────────────┐ +56)│ DataSourceExec │ +57)│ -------------------- │ +58)│ files: 1 │ +59)│ format: csv │ +60)└───────────────────────────┘ # Query with nested loop join. query TT @@ -1205,13 +1344,19 @@ physical_plan 20)-----------------------------└─────────────┬─────────────┘ 21)-----------------------------┌─────────────┴─────────────┐ 22)-----------------------------│ RepartitionExec │ -23)-----------------------------└─────────────┬─────────────┘ -24)-----------------------------┌─────────────┴─────────────┐ -25)-----------------------------│ DataSourceExec │ -26)-----------------------------│ -------------------- │ -27)-----------------------------│ files: 1 │ -28)-----------------------------│ format: parquet │ -29)-----------------------------└───────────────────────────┘ +23)-----------------------------│ -------------------- │ +24)-----------------------------│ output_partition_count: │ +25)-----------------------------│ 1 │ +26)-----------------------------│ │ +27)-----------------------------│ partitioning_scheme: │ +28)-----------------------------│ RoundRobinBatch(4) │ +29)-----------------------------└─────────────┬─────────────┘ +30)-----------------------------┌─────────────┴─────────────┐ +31)-----------------------------│ DataSourceExec │ +32)-----------------------------│ -------------------- │ +33)-----------------------------│ files: 1 │ +34)-----------------------------│ format: parquet │ +35)-----------------------------└───────────────────────────┘ # Query with cross join. query TT @@ -1227,16 +1372,19 @@ physical_plan 03)└─────────────┬─────────────┘ │ 04)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ 05)│ DataSourceExec ││ RepartitionExec │ -06)│ -------------------- ││ │ -07)│ files: 1 ││ │ -08)│ format: csv ││ │ -09)└───────────────────────────┘└─────────────┬─────────────┘ -10)-----------------------------┌─────────────┴─────────────┐ -11)-----------------------------│ DataSourceExec │ -12)-----------------------------│ -------------------- │ -13)-----------------------------│ files: 1 │ -14)-----------------------------│ format: parquet │ -15)-----------------------------└───────────────────────────┘ +06)│ -------------------- ││ -------------------- │ +07)│ files: 1 ││ output_partition_count: │ +08)│ format: csv ││ 1 │ +09)│ ││ │ +10)│ ││ partitioning_scheme: │ +11)│ ││ RoundRobinBatch(4) │ +12)└───────────────────────────┘└─────────────┬─────────────┘ +13)-----------------------------┌─────────────┴─────────────┐ +14)-----------------------------│ DataSourceExec │ +15)-----------------------------│ -------------------- │ +16)-----------------------------│ files: 1 │ +17)-----------------------------│ format: parquet │ +18)-----------------------------└───────────────────────────┘ # Query with sort merge join. @@ -1327,13 +1475,19 @@ physical_plan 12)└─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐ 14)│ RepartitionExec │ -15)└─────────────┬─────────────┘ -16)┌─────────────┴─────────────┐ -17)│ StreamingTableExec │ -18)│ -------------------- │ -19)│ infinite: true │ -20)│ limit: None │ -21)└───────────────────────────┘ +15)│ -------------------- │ +16)│ output_partition_count: │ +17)│ 1 │ +18)│ │ +19)│ partitioning_scheme: │ +20)│ RoundRobinBatch(4) │ +21)└─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐ +23)│ StreamingTableExec │ +24)│ -------------------- │ +25)│ infinite: true │ +26)│ limit: None │ +27)└───────────────────────────┘ # constant ticker, CAST(time AS DATE) = time, order by time @@ -1362,13 +1516,19 @@ physical_plan 13)└─────────────┬─────────────┘ 14)┌─────────────┴─────────────┐ 15)│ RepartitionExec │ -16)└─────────────┬─────────────┘ -17)┌─────────────┴─────────────┐ -18)│ StreamingTableExec │ -19)│ -------------------- │ -20)│ infinite: true │ -21)│ limit: None │ -22)└───────────────────────────┘ +16)│ -------------------- │ +17)│ output_partition_count: │ +18)│ 1 │ +19)│ │ +20)│ partitioning_scheme: │ +21)│ RoundRobinBatch(4) │ +22)└─────────────┬─────────────┘ +23)┌─────────────┴─────────────┐ +24)│ StreamingTableExec │ +25)│ -------------------- │ +26)│ infinite: true │ +27)│ limit: None │ +28)└───────────────────────────┘ # same thing but order by date query TT @@ -1396,13 +1556,19 @@ physical_plan 13)└─────────────┬─────────────┘ 14)┌─────────────┴─────────────┐ 15)│ RepartitionExec │ -16)└─────────────┬─────────────┘ -17)┌─────────────┴─────────────┐ -18)│ StreamingTableExec │ -19)│ -------------------- │ -20)│ infinite: true │ -21)│ limit: None │ -22)└───────────────────────────┘ +16)│ -------------------- │ +17)│ output_partition_count: │ +18)│ 1 │ +19)│ │ +20)│ partitioning_scheme: │ +21)│ RoundRobinBatch(4) │ +22)└─────────────┬─────────────┘ +23)┌─────────────┴─────────────┐ +24)│ StreamingTableExec │ +25)│ -------------------- │ +26)│ infinite: true │ +27)│ limit: None │ +28)└───────────────────────────┘ # same thing but order by ticker query TT @@ -1430,13 +1596,19 @@ physical_plan 13)└─────────────┬─────────────┘ 14)┌─────────────┴─────────────┐ 15)│ RepartitionExec │ -16)└─────────────┬─────────────┘ -17)┌─────────────┴─────────────┐ -18)│ StreamingTableExec │ -19)│ -------------------- │ -20)│ infinite: true │ -21)│ limit: None │ -22)└───────────────────────────┘ +16)│ -------------------- │ +17)│ output_partition_count: │ +18)│ 1 │ +19)│ │ +20)│ partitioning_scheme: │ +21)│ RoundRobinBatch(4) │ +22)└─────────────┬─────────────┘ +23)┌─────────────┴─────────────┐ +24)│ StreamingTableExec │ +25)│ -------------------- │ +26)│ infinite: true │ +27)│ limit: None │ +28)└───────────────────────────┘ # same thing but order by time, date @@ -1465,13 +1637,19 @@ physical_plan 13)└─────────────┬─────────────┘ 14)┌─────────────┴─────────────┐ 15)│ RepartitionExec │ -16)└─────────────┬─────────────┘ -17)┌─────────────┴─────────────┐ -18)│ StreamingTableExec │ -19)│ -------------------- │ -20)│ infinite: true │ -21)│ limit: None │ -22)└───────────────────────────┘ +16)│ -------------------- │ +17)│ output_partition_count: │ +18)│ 1 │ +19)│ │ +20)│ partitioning_scheme: │ +21)│ RoundRobinBatch(4) │ +22)└─────────────┬─────────────┘ +23)┌─────────────┴─────────────┐ +24)│ StreamingTableExec │ +25)│ -------------------- │ +26)│ infinite: true │ +27)│ limit: None │ +28)└───────────────────────────┘ @@ -1501,10 +1679,16 @@ physical_plan 12)└─────────────┬─────────────┘ 13)┌─────────────┴─────────────┐ 14)│ RepartitionExec │ -15)└─────────────┬─────────────┘ -16)┌─────────────┴─────────────┐ -17)│ StreamingTableExec │ -18)│ -------------------- │ -19)│ infinite: true │ -20)│ limit: None │ -21)└───────────────────────────┘ +15)│ -------------------- │ +16)│ output_partition_count: │ +17)│ 1 │ +18)│ │ +19)│ partitioning_scheme: │ +20)│ RoundRobinBatch(4) │ +21)└─────────────┬─────────────┘ +22)┌─────────────┴─────────────┐ +23)│ StreamingTableExec │ +24)│ -------------------- │ +25)│ infinite: true │ +26)│ limit: None │ +27)└───────────────────────────┘ From 6a354496d07e633e1d200e858ff6af3b8544b8fe Mon Sep 17 00:00:00 2001 From: Alan Tang Date: Tue, 11 Mar 2025 09:44:05 +0800 Subject: [PATCH 2/3] feat: implement tree rendering for WorkTableExec Signed-off-by: Alan Tang --- datafusion/physical-plan/src/work_table.rs | 3 +- .../sqllogictest/test_files/explain_tree.slt | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/datafusion/physical-plan/src/work_table.rs b/datafusion/physical-plan/src/work_table.rs index f082b05410dd..126a7d0bba29 100644 --- a/datafusion/physical-plan/src/work_table.rs +++ b/datafusion/physical-plan/src/work_table.rs @@ -163,8 +163,7 @@ impl DisplayAs for WorkTableExec { write!(f, "WorkTableExec: name={}", self.name) } DisplayFormatType::TreeRender => { - // TODO: collect info - write!(f, "") + write!(f, "name={}", self.name) } } } diff --git a/datafusion/sqllogictest/test_files/explain_tree.slt b/datafusion/sqllogictest/test_files/explain_tree.slt index bc4a033ab728..31dbbf4c1723 100644 --- a/datafusion/sqllogictest/test_files/explain_tree.slt +++ b/datafusion/sqllogictest/test_files/explain_tree.slt @@ -1692,3 +1692,61 @@ physical_plan 25)│ infinite: true │ 26)│ limit: None │ 27)└───────────────────────────┘ + + + +# Test explain tree for WorkTableExec +query TT +EXPLAIN WITH RECURSIVE nodes AS ( + SELECT 1 as id + UNION ALL + SELECT id + 1 as id + FROM nodes + WHERE id < 10 +) +SELECT * FROM nodes +---- +logical_plan +01)SubqueryAlias: nodes +02)--RecursiveQuery: is_distinct=false +03)----Projection: Int64(1) AS id +04)------EmptyRelation +05)----Projection: nodes.id + Int64(1) AS id +06)------Filter: nodes.id < Int64(10) +07)--------TableScan: nodes +physical_plan +01)┌───────────────────────────┐ +02)│ RecursiveQueryExec ├──────────────┐ +03)└─────────────┬─────────────┘ │ +04)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +05)│ ProjectionExec ││ CoalescePartitionsExec │ +06)│ -------------------- ││ │ +07)│ id: 1 ││ │ +08)└─────────────┬─────────────┘└─────────────┬─────────────┘ +09)┌─────────────┴─────────────┐┌─────────────┴─────────────┐ +10)│ PlaceholderRowExec ││ ProjectionExec │ +11)│ ││ -------------------- │ +12)│ ││ id: id@0 + 1 │ +13)└───────────────────────────┘└─────────────┬─────────────┘ +14)-----------------------------┌─────────────┴─────────────┐ +15)-----------------------------│ CoalesceBatchesExec │ +16)-----------------------------└─────────────┬─────────────┘ +17)-----------------------------┌─────────────┴─────────────┐ +18)-----------------------------│ FilterExec │ +19)-----------------------------│ -------------------- │ +20)-----------------------------│ predicate: id@0 < 10 │ +21)-----------------------------└─────────────┬─────────────┘ +22)-----------------------------┌─────────────┴─────────────┐ +23)-----------------------------│ RepartitionExec │ +24)-----------------------------│ -------------------- │ +25)-----------------------------│ output_partition_count: │ +26)-----------------------------│ 1 │ +27)-----------------------------│ │ +28)-----------------------------│ partitioning_scheme: │ +29)-----------------------------│ RoundRobinBatch(4) │ +30)-----------------------------└─────────────┬─────────────┘ +31)-----------------------------┌─────────────┴─────────────┐ +32)-----------------------------│ WorkTableExec │ +33)-----------------------------│ -------------------- │ +34)-----------------------------│ name: nodes │ +35)-----------------------------└───────────────────────────┘ From f597397d3a452c1ea5a045902b9066540486f8d6 Mon Sep 17 00:00:00 2001 From: Alan Tang Date: Tue, 11 Mar 2025 10:09:24 +0800 Subject: [PATCH 3/3] bug: fix clippy error Signed-off-by: Alan Tang --- datafusion/physical-plan/src/repartition/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/datafusion/physical-plan/src/repartition/mod.rs b/datafusion/physical-plan/src/repartition/mod.rs index 19d789c96f7b..2b2548c8723c 100644 --- a/datafusion/physical-plan/src/repartition/mod.rs +++ b/datafusion/physical-plan/src/repartition/mod.rs @@ -514,10 +514,7 @@ impl DisplayAs for RepartitionExec { self.input.output_partitioning().partition_count() )?; if self.preserve_order { - writeln!(f, ", preserve_order={}", "SortPreserving")?; - } - if let Some(sort_exprs) = self.sort_exprs() { - write!(f, "sort_exprs={}", sort_exprs.clone())?; + writeln!(f, "preserve_order={}", self.preserve_order)?; } Ok(()) }