From b9ce90f85b9c68d94dc1528fe3bbb2a972ecb6d7 Mon Sep 17 00:00:00 2001 From: DreaMer963 Date: Tue, 25 Jan 2022 23:45:09 +0800 Subject: [PATCH] feat: add join type for logical plan display --- datafusion/src/logical_plan/builder.rs | 2 +- datafusion/src/logical_plan/plan.rs | 25 ++++++++++++++-- datafusion/src/optimizer/filter_push_down.rs | 30 +++++++++---------- .../src/optimizer/projection_push_down.rs | 6 ++-- datafusion/src/sql/planner.rs | 22 +++++++------- datafusion/tests/sql/explain_analyze.rs | 6 ++-- 6 files changed, 56 insertions(+), 35 deletions(-) diff --git a/datafusion/src/logical_plan/builder.rs b/datafusion/src/logical_plan/builder.rs index fc609390bcc0..613c8e950c93 100644 --- a/datafusion/src/logical_plan/builder.rs +++ b/datafusion/src/logical_plan/builder.rs @@ -1150,7 +1150,7 @@ mod tests { // id column should only show up once in projection let expected = "Projection: #t1.id, #t1.first_name, #t1.last_name, #t1.state, #t1.salary, #t2.first_name, #t2.last_name, #t2.state, #t2.salary\ - \n Join: Using #t1.id = #t2.id\ + \n Inner Join: Using #t1.id = #t2.id\ \n TableScan: t1 projection=None\ \n TableScan: t2 projection=None"; diff --git a/datafusion/src/logical_plan/plan.rs b/datafusion/src/logical_plan/plan.rs index b40dfc0103fc..3d49e5484eab 100644 --- a/datafusion/src/logical_plan/plan.rs +++ b/datafusion/src/logical_plan/plan.rs @@ -25,6 +25,7 @@ use crate::error::DataFusionError; use crate::logical_plan::dfschema::DFSchemaRef; use crate::sql::parser::FileType; use arrow::datatypes::{DataType, Field, Schema, SchemaRef}; +use std::fmt::Formatter; use std::{ collections::HashSet, fmt::{self, Display}, @@ -48,6 +49,20 @@ pub enum JoinType { Anti, } +impl Display for JoinType { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let join_type = match self { + JoinType::Inner => "Inner", + JoinType::Left => "Left", + JoinType::Right => "Right", + JoinType::Full => "Full", + JoinType::Semi => "Semi", + JoinType::Anti => "Anti", + }; + write!(f, "{}", join_type) + } +} + /// Join constraint #[derive(Debug, Clone, Copy)] pub enum JoinConstraint { @@ -934,16 +949,22 @@ impl LogicalPlan { LogicalPlan::Join(Join { on: ref keys, join_constraint, + join_type, .. }) => { let join_expr: Vec = keys.iter().map(|(l, r)| format!("{} = {}", l, r)).collect(); match join_constraint { JoinConstraint::On => { - write!(f, "Join: {}", join_expr.join(", ")) + write!(f, "{} Join: {}", join_type, join_expr.join(", ")) } JoinConstraint::Using => { - write!(f, "Join: Using {}", join_expr.join(", ")) + write!( + f, + "{} Join: Using {}", + join_type, + join_expr.join(", ") + ) } } } diff --git a/datafusion/src/optimizer/filter_push_down.rs b/datafusion/src/optimizer/filter_push_down.rs index 6141af18a780..ababb52020d7 100644 --- a/datafusion/src/optimizer/filter_push_down.rs +++ b/datafusion/src/optimizer/filter_push_down.rs @@ -1014,7 +1014,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test.a <= Int64(1)\ - \n Join: #test.a = #test2.a\ + \n Inner Join: #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None" @@ -1022,7 +1022,7 @@ mod tests { // filter sent to side before the join let expected = "\ - Join: #test.a = #test2.a\ + Inner Join: #test.a = #test2.a\ \n Filter: #test.a <= Int64(1)\ \n TableScan: test projection=None\ \n Projection: #test2.a\ @@ -1055,7 +1055,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Inner Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None" @@ -1063,7 +1063,7 @@ mod tests { // filter sent to side before the join let expected = "\ - Join: Using #test.a = #test2.a\ + Inner Join: Using #test.a = #test2.a\ \n Filter: #test.a <= Int64(1)\ \n TableScan: test projection=None\ \n Projection: #test2.a\ @@ -1099,7 +1099,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test.c <= #test2.b\ - \n Join: #test.a = #test2.a\ + \n Inner Join: #test.a = #test2.a\ \n Projection: #test.a, #test.c\ \n TableScan: test projection=None\ \n Projection: #test2.a, #test2.b\ @@ -1138,7 +1138,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test.b <= Int64(1)\ - \n Join: #test.a = #test2.a\ + \n Inner Join: #test.a = #test2.a\ \n Projection: #test.a, #test.b\ \n TableScan: test projection=None\ \n Projection: #test2.a, #test2.c\ @@ -1146,7 +1146,7 @@ mod tests { ); let expected = "\ - Join: #test.a = #test2.a\ + Inner Join: #test.a = #test2.a\ \n Projection: #test.a, #test.b\ \n Filter: #test.b <= Int64(1)\ \n TableScan: test projection=None\ @@ -1180,7 +1180,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test2.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Left Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None" @@ -1189,7 +1189,7 @@ mod tests { // filter not duplicated nor pushed down - i.e. noop let expected = "\ Filter: #test2.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Left Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None"; @@ -1221,7 +1221,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Right Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None" @@ -1230,7 +1230,7 @@ mod tests { // filter not duplicated nor pushed down - i.e. noop let expected = "\ Filter: #test.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Right Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None"; @@ -1262,7 +1262,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Left Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None" @@ -1270,7 +1270,7 @@ mod tests { // filter sent to left side of the join, not the right let expected = "\ - Join: Using #test.a = #test2.a\ + Left Join: Using #test.a = #test2.a\ \n Filter: #test.a <= Int64(1)\ \n TableScan: test projection=None\ \n Projection: #test2.a\ @@ -1303,7 +1303,7 @@ mod tests { format!("{:?}", plan), "\ Filter: #test2.a <= Int64(1)\ - \n Join: Using #test.a = #test2.a\ + \n Right Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n TableScan: test2 projection=None" @@ -1311,7 +1311,7 @@ mod tests { // filter sent to right side of join, not duplicated to the left let expected = "\ - Join: Using #test.a = #test2.a\ + Right Join: Using #test.a = #test2.a\ \n TableScan: test projection=None\ \n Projection: #test2.a\ \n Filter: #test2.a <= Int64(1)\ diff --git a/datafusion/src/optimizer/projection_push_down.rs b/datafusion/src/optimizer/projection_push_down.rs index fb45e981612e..1a64a44c52d6 100644 --- a/datafusion/src/optimizer/projection_push_down.rs +++ b/datafusion/src/optimizer/projection_push_down.rs @@ -593,7 +593,7 @@ mod tests { // make sure projections are pushed down to both table scans let expected = "Projection: #test.a, #test.b, #test2.c1\ - \n Join: #test.a = #test2.c1\ + \n Left Join: #test.a = #test2.c1\ \n TableScan: test projection=Some([0, 1])\ \n TableScan: test2 projection=Some([0])"; @@ -634,7 +634,7 @@ mod tests { // make sure projections are pushed down to both table scans let expected = "Projection: #test.a, #test.b\ - \n Join: #test.a = #test2.c1\ + \n Left Join: #test.a = #test2.c1\ \n TableScan: test projection=Some([0, 1])\ \n TableScan: test2 projection=Some([0])"; @@ -673,7 +673,7 @@ mod tests { // make sure projections are pushed down to table scan let expected = "Projection: #test.a, #test.b\ - \n Join: Using #test.a = #test2.a\ + \n Left Join: Using #test.a = #test2.a\ \n TableScan: test projection=Some([0, 1])\ \n TableScan: test2 projection=Some([0])"; diff --git a/datafusion/src/sql/planner.rs b/datafusion/src/sql/planner.rs index e951a3a702a1..9da54cad4daa 100644 --- a/datafusion/src/sql/planner.rs +++ b/datafusion/src/sql/planner.rs @@ -3289,7 +3289,7 @@ mod tests { JOIN orders \ ON id = customer_id"; let expected = "Projection: #person.id, #orders.order_id\ - \n Join: #person.id = #orders.customer_id\ + \n Inner Join: #person.id = #orders.customer_id\ \n TableScan: person projection=None\ \n TableScan: orders projection=None"; quick_test(sql, expected); @@ -3303,7 +3303,7 @@ mod tests { ON id = customer_id AND order_id > 1 "; let expected = "Projection: #person.id, #orders.order_id\ \n Filter: #orders.order_id > Int64(1)\ - \n Join: #person.id = #orders.customer_id\ + \n Inner Join: #person.id = #orders.customer_id\ \n TableScan: person projection=None\ \n TableScan: orders projection=None"; quick_test(sql, expected); @@ -3316,7 +3316,7 @@ mod tests { LEFT JOIN orders \ ON id = customer_id AND order_id > 1"; let expected = "Projection: #person.id, #orders.order_id\ - \n Join: #person.id = #orders.customer_id\ + \n Left Join: #person.id = #orders.customer_id\ \n TableScan: person projection=None\ \n Filter: #orders.order_id > Int64(1)\ \n TableScan: orders projection=None"; @@ -3330,7 +3330,7 @@ mod tests { RIGHT JOIN orders \ ON id = customer_id AND id > 1"; let expected = "Projection: #person.id, #orders.order_id\ - \n Join: #person.id = #orders.customer_id\ + \n Right Join: #person.id = #orders.customer_id\ \n Filter: #person.id > Int64(1)\ \n TableScan: person projection=None\ \n TableScan: orders projection=None"; @@ -3344,7 +3344,7 @@ mod tests { JOIN orders \ ON person.id = orders.customer_id"; let expected = "Projection: #person.id, #orders.order_id\ - \n Join: #person.id = #orders.customer_id\ + \n Inner Join: #person.id = #orders.customer_id\ \n TableScan: person projection=None\ \n TableScan: orders projection=None"; quick_test(sql, expected); @@ -3357,7 +3357,7 @@ mod tests { JOIN person as person2 \ USING (id)"; let expected = "Projection: #person.first_name, #person.id\ - \n Join: Using #person.id = #person2.id\ + \n Inner Join: Using #person.id = #person2.id\ \n TableScan: person projection=None\ \n TableScan: person2 projection=None"; quick_test(sql, expected); @@ -3370,7 +3370,7 @@ mod tests { JOIN lineitem as lineitem2 \ USING (l_item_id)"; let expected = "Projection: #lineitem.l_item_id, #lineitem.l_description, #lineitem.price, #lineitem2.l_description, #lineitem2.price\ - \n Join: Using #lineitem.l_item_id = #lineitem2.l_item_id\ + \n Inner Join: Using #lineitem.l_item_id = #lineitem2.l_item_id\ \n TableScan: lineitem projection=None\ \n TableScan: lineitem2 projection=None"; quick_test(sql, expected); @@ -3384,8 +3384,8 @@ mod tests { JOIN lineitem ON o_item_id = l_item_id"; let expected = "Projection: #person.id, #orders.order_id, #lineitem.l_description\ - \n Join: #orders.o_item_id = #lineitem.l_item_id\ - \n Join: #person.id = #orders.customer_id\ + \n Inner Join: #orders.o_item_id = #lineitem.l_item_id\ + \n Inner Join: #person.id = #orders.customer_id\ \n TableScan: person projection=None\ \n TableScan: orders projection=None\ \n TableScan: lineitem projection=None"; @@ -3918,8 +3918,8 @@ mod tests { fn cross_join_to_inner_join() { let sql = "select person.id from person, orders, lineitem where person.id = lineitem.l_item_id and orders.o_item_id = lineitem.l_description;"; let expected = "Projection: #person.id\ - \n Join: #lineitem.l_description = #orders.o_item_id\ - \n Join: #person.id = #lineitem.l_item_id\ + \n Inner Join: #lineitem.l_description = #orders.o_item_id\ + \n Inner Join: #person.id = #lineitem.l_item_id\ \n TableScan: person projection=None\ \n TableScan: lineitem projection=None\ \n TableScan: orders projection=None"; diff --git a/datafusion/tests/sql/explain_analyze.rs b/datafusion/tests/sql/explain_analyze.rs index 7c1fa69ab73f..2bd78ec728f5 100644 --- a/datafusion/tests/sql/explain_analyze.rs +++ b/datafusion/tests/sql/explain_analyze.rs @@ -616,9 +616,9 @@ order by Sort: #revenue DESC NULLS FIRST\ \n Projection: #customer.c_custkey, #customer.c_name, #SUM(lineitem.l_extendedprice * Int64(1) - lineitem.l_discount) AS revenue, #customer.c_acctbal, #nation.n_name, #customer.c_address, #customer.c_phone, #customer.c_comment\ \n Aggregate: groupBy=[[#customer.c_custkey, #customer.c_name, #customer.c_acctbal, #customer.c_phone, #nation.n_name, #customer.c_address, #customer.c_comment]], aggr=[[SUM(#lineitem.l_extendedprice * Int64(1) - #lineitem.l_discount)]]\ - \n Join: #customer.c_nationkey = #nation.n_nationkey\ - \n Join: #orders.o_orderkey = #lineitem.l_orderkey\ - \n Join: #customer.c_custkey = #orders.o_custkey\ + \n Inner Join: #customer.c_nationkey = #nation.n_nationkey\ + \n Inner Join: #orders.o_orderkey = #lineitem.l_orderkey\ + \n Inner Join: #customer.c_custkey = #orders.o_custkey\ \n TableScan: customer projection=Some([0, 1, 2, 3, 4, 5, 7])\ \n Filter: #orders.o_orderdate >= Date32(\"8674\") AND #orders.o_orderdate < Date32(\"8766\")\ \n TableScan: orders projection=Some([0, 1, 4]), filters=[#orders.o_orderdate >= Date32(\"8674\"), #orders.o_orderdate < Date32(\"8766\")]\