diff --git a/datafusion/src/physical_plan/expressions/min_max.rs b/datafusion/src/physical_plan/expressions/min_max.rs index 97486680f2e09..9e5b1e095cd6f 100644 --- a/datafusion/src/physical_plan/expressions/min_max.rs +++ b/datafusion/src/physical_plan/expressions/min_max.rs @@ -38,6 +38,18 @@ use arrow::{ use super::format_state_name; +// Min/max aggregation can take Dictionary encode input but always produces unpacked +// (aka non Dictionary) output. We need to adjust the output data type to reflect this. +// The reason min/max aggregate produces unpacked output because there is only one +// min/max value per group; there is no needs to keep them Dictionary encode +fn min_max_aggregate_data_type(input_type: DataType) -> DataType { + if let DataType::Dictionary(_, value_type) = input_type { + *value_type + } else { + input_type + } +} + /// MAX aggregate expression #[derive(Debug)] pub struct Max { @@ -57,7 +69,7 @@ impl Max { Self { name: name.into(), expr, - data_type, + data_type: min_max_aggregate_data_type(data_type), nullable: true, } } @@ -379,7 +391,7 @@ impl Min { Self { name: name.into(), expr, - data_type, + data_type: min_max_aggregate_data_type(data_type), nullable: true, } } diff --git a/datafusion/src/physical_plan/planner.rs b/datafusion/src/physical_plan/planner.rs index fd0421b5e0bad..9c6aeb8f65108 100644 --- a/datafusion/src/physical_plan/planner.rs +++ b/datafusion/src/physical_plan/planner.rs @@ -1422,6 +1422,10 @@ impl DefaultPhysicalPlanner { new_plan = optimizer.optimize(new_plan, &ctx_state.config)?; observer(new_plan.as_ref(), optimizer.as_ref()) } + debug!( + "Optimized physical plan short version:\n{}\n", + displayable(new_plan.as_ref()).indent() + ); debug!("Optimized physical plan:\n{:?}", new_plan); Ok(new_plan) } diff --git a/datafusion/tests/sql.rs b/datafusion/tests/sql.rs index 6cd1d3822bce9..c1424ce8bd1d7 100644 --- a/datafusion/tests/sql.rs +++ b/datafusion/tests/sql.rs @@ -3976,6 +3976,18 @@ async fn query_on_string_dictionary() -> Result<()> { let expected = vec![vec!["2"]]; assert_eq!(expected, actual); + // aggregation min + let sql = "SELECT MIN(d1) FROM test"; + let actual = execute(&mut ctx, sql).await; + let expected = vec![vec!["one"]]; + assert_eq!(expected, actual); + + // aggregation max + let sql = "SELECT MAX(d1) FROM test"; + let actual = execute(&mut ctx, sql).await; + let expected = vec![vec!["three"]]; + assert_eq!(expected, actual); + // grouping let sql = "SELECT d1, COUNT(*) FROM test group by d1"; let mut actual = execute(&mut ctx, sql).await;