@@ -129,7 +129,6 @@ fn is_single_distinct_agg(
129129 let mut fields_set = HashSet :: new ( ) ;
130130 let mut aggregate_count = 0 ;
131131 let mut distinct_aggs = vec ! [ ] ;
132- let mut has_count_rollup = false ;
133132 for expr in aggr_expr {
134133 if let Expr :: AggregateFunction ( AggregateFunction {
135134 func,
@@ -153,7 +152,7 @@ fn is_single_distinct_agg(
153152 }
154153 distinct_aggs. push ( ( func, args. as_slice ( ) ) ) ;
155154 } else if count_rollup. is_some_and ( |rollup| rollup. is_count ( func) ) {
156- has_count_rollup = true ;
155+ // count is allowed
157156 } else if func. name ( ) != "sum"
158157 && func. name ( ) . to_lowercase ( ) != "min"
159158 && func. name ( ) . to_lowercase ( ) != "max"
@@ -167,14 +166,13 @@ fn is_single_distinct_agg(
167166 if aggregate_count != aggr_expr. len ( ) || fields_set. len ( ) != 1 {
168167 return Ok ( false ) ;
169168 }
170- if has_count_rollup && ! rewrite_pays_for_count ( & distinct_aggs, input_schema) ? {
169+ if ! rewrite_pays ( & distinct_aggs, input_schema) ? {
171170 return Ok ( false ) ;
172171 }
173172 Ok ( true )
174173}
175174
176- /// Whether the rewrite is worth extending to a plan that only qualifies because
177- /// of the non-distinct `count`.
175+ /// Whether the rewrite is worth extending to a plan.
178176///
179177/// The rewrite is not free: every other aggregate moves down to the inner group
180178/// by, which has a row per `(group, distinct value)` pair rather than per group,
@@ -189,12 +187,8 @@ fn is_single_distinct_agg(
189187///
190188/// This is a proxy: what actually decides the outcome is the cost per distinct
191189/// value on each side, which this rule cannot see. It is deliberately
192- /// conservative in the direction that leaves a plan alone. The pre-existing
193- /// tolerance of a non-distinct `sum`, `min` or `max` is not gated, since
194- /// narrowing it would change plans that have always been rewritten.
195- ///
196- /// Measured in <https://github.com/apache/datafusion/pull/24859>.
197- fn rewrite_pays_for_count (
190+ /// conservative in the direction that leaves a plan alone.
191+ fn rewrite_pays (
198192 distinct_aggs : & [ ( & Arc < AggregateUDF > , & [ Expr ] ) ] ,
199193 input_schema : & DFSchema ,
200194) -> Result < bool > {
@@ -634,11 +628,9 @@ mod tests {
634628 // Should work
635629 assert_optimized_plan_equal ! (
636630 plan,
637- @r"
638- Projection: count(alias1) AS count(DISTINCT test.b) [count(DISTINCT test.b):Int64]
639- Aggregate: groupBy=[[]], aggr=[[count(alias1)]] [count(alias1):Int64]
640- Aggregate: groupBy=[[test.b AS alias1]], aggr=[[]] [alias1:UInt32]
641- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
631+ @"
632+ Aggregate: groupBy=[[]], aggr=[[count(DISTINCT test.b)]] [count(DISTINCT test.b):Int64]
633+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
642634 "
643635 )
644636 }
@@ -720,11 +712,9 @@ mod tests {
720712
721713 assert_optimized_plan_equal ! (
722714 plan,
723- @r"
724- Projection: count(alias1) AS count(DISTINCT Int32(2) * test.b) [count(DISTINCT Int32(2) * test.b):Int64]
725- Aggregate: groupBy=[[]], aggr=[[count(alias1)]] [count(alias1):Int64]
726- Aggregate: groupBy=[[Int32(2) * test.b AS alias1]], aggr=[[]] [alias1:Int64]
727- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
715+ @"
716+ Aggregate: groupBy=[[]], aggr=[[count(DISTINCT Int32(2) * test.b)]] [count(DISTINCT Int32(2) * test.b):Int64]
717+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
728718 "
729719 )
730720 }
@@ -740,11 +730,9 @@ mod tests {
740730 // Should work
741731 assert_optimized_plan_equal ! (
742732 plan,
743- @r"
744- Projection: test.a, count(alias1) AS count(DISTINCT test.b) [a:UInt32, count(DISTINCT test.b):Int64]
745- Aggregate: groupBy=[[test.a]], aggr=[[count(alias1)]] [a:UInt32, count(alias1):Int64]
746- Aggregate: groupBy=[[test.a, test.b AS alias1]], aggr=[[]] [a:UInt32, alias1:UInt32]
747- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
733+ @"
734+ Aggregate: groupBy=[[test.a]], aggr=[[count(DISTINCT test.b)]] [a:UInt32, count(DISTINCT test.b):Int64]
735+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
748736 "
749737 )
750738 }
@@ -784,11 +772,9 @@ mod tests {
784772 // Should work
785773 assert_optimized_plan_equal ! (
786774 plan,
787- @r"
788- Projection: test.a, count(alias1) AS count(DISTINCT test.b), max(alias1) AS max(DISTINCT test.b) [a:UInt32, count(DISTINCT test.b):Int64, max(DISTINCT test.b):UInt32;N]
789- Aggregate: groupBy=[[test.a]], aggr=[[count(alias1), max(alias1)]] [a:UInt32, count(alias1):Int64, max(alias1):UInt32;N]
790- Aggregate: groupBy=[[test.a, test.b AS alias1]], aggr=[[]] [a:UInt32, alias1:UInt32]
791- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
775+ @"
776+ Aggregate: groupBy=[[test.a]], aggr=[[count(DISTINCT test.b), max(DISTINCT test.b)]] [a:UInt32, count(DISTINCT test.b):Int64, max(DISTINCT test.b):UInt32;N]
777+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
792778 "
793779 )
794780 }
@@ -856,11 +842,9 @@ mod tests {
856842 // exactly as before
857843 assert_optimized_plan_equal ! (
858844 plan,
859- @r"
860- Projection: test.a, count(alias1) AS count(DISTINCT test.b), sum(alias2) AS sum(test.c) [a:UInt32, count(DISTINCT test.b):Int64, sum(test.c):UInt64;N]
861- Aggregate: groupBy=[[test.a]], aggr=[[count(alias1), sum(alias2)]] [a:UInt32, count(alias1):Int64, sum(alias2):UInt64;N]
862- Aggregate: groupBy=[[test.a, test.b AS alias1]], aggr=[[sum(test.c) AS alias2]] [a:UInt32, alias1:UInt32, alias2:UInt64;N]
863- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
845+ @"
846+ Aggregate: groupBy=[[test.a]], aggr=[[count(DISTINCT test.b), sum(test.c)]] [a:UInt32, count(DISTINCT test.b):Int64, sum(test.c):UInt64;N]
847+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
864848 "
865849 )
866850 }
@@ -923,11 +907,9 @@ mod tests {
923907 // Should work
924908 assert_optimized_plan_equal ! (
925909 plan,
926- @r"
927- Projection: group_alias_0 AS test.a + Int32(1), count(alias1) AS count(DISTINCT test.c) [test.a + Int32(1):Int64, count(DISTINCT test.c):Int64]
928- Aggregate: groupBy=[[group_alias_0]], aggr=[[count(alias1)]] [group_alias_0:Int64, count(alias1):Int64]
929- Aggregate: groupBy=[[test.a + Int32(1) AS group_alias_0, test.c AS alias1]], aggr=[[]] [group_alias_0:Int64, alias1:UInt32]
930- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
910+ @"
911+ Aggregate: groupBy=[[test.a + Int32(1)]], aggr=[[count(DISTINCT test.c)]] [test.a + Int32(1):Int64, count(DISTINCT test.c):Int64]
912+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
931913 "
932914 )
933915 }
@@ -950,11 +932,9 @@ mod tests {
950932 // Should work
951933 assert_optimized_plan_equal ! (
952934 plan,
953- @r"
954- Projection: test.a, sum(alias2) AS sum(test.c), count(alias1) AS count(DISTINCT test.b), max(alias1) AS max(DISTINCT test.b) [a:UInt32, sum(test.c):UInt64;N, count(DISTINCT test.b):Int64, max(DISTINCT test.b):UInt32;N]
955- Aggregate: groupBy=[[test.a]], aggr=[[sum(alias2), count(alias1), max(alias1)]] [a:UInt32, sum(alias2):UInt64;N, count(alias1):Int64, max(alias1):UInt32;N]
956- Aggregate: groupBy=[[test.a, test.b AS alias1]], aggr=[[sum(test.c) AS alias2]] [a:UInt32, alias1:UInt32, alias2:UInt64;N]
957- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
935+ @"
936+ Aggregate: groupBy=[[test.a]], aggr=[[sum(test.c), count(DISTINCT test.b), max(DISTINCT test.b)]] [a:UInt32, sum(test.c):UInt64;N, count(DISTINCT test.b):Int64, max(DISTINCT test.b):UInt32;N]
937+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
958938 "
959939 )
960940 }
@@ -973,11 +953,9 @@ mod tests {
973953 // Should work
974954 assert_optimized_plan_equal ! (
975955 plan,
976- @r"
977- Projection: test.a, sum(alias2) AS sum(test.c), max(alias3) AS max(test.c), count(alias1) AS count(DISTINCT test.b) [a:UInt32, sum(test.c):UInt64;N, max(test.c):UInt32;N, count(DISTINCT test.b):Int64]
978- Aggregate: groupBy=[[test.a]], aggr=[[sum(alias2), max(alias3), count(alias1)]] [a:UInt32, sum(alias2):UInt64;N, max(alias3):UInt32;N, count(alias1):Int64]
979- Aggregate: groupBy=[[test.a, test.b AS alias1]], aggr=[[sum(test.c) AS alias2, max(test.c) AS alias3]] [a:UInt32, alias1:UInt32, alias2:UInt64;N, alias3:UInt32;N]
980- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
956+ @"
957+ Aggregate: groupBy=[[test.a]], aggr=[[sum(test.c), max(test.c), count(DISTINCT test.b)]] [a:UInt32, sum(test.c):UInt64;N, max(test.c):UInt32;N, count(DISTINCT test.b):Int64]
958+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
981959 "
982960 )
983961 }
@@ -996,11 +974,9 @@ mod tests {
996974 // Should work
997975 assert_optimized_plan_equal ! (
998976 plan,
999- @r"
1000- Projection: test.c, min(alias2) AS min(test.a), count(alias1) AS count(DISTINCT test.b) [c:UInt32, min(test.a):UInt32;N, count(DISTINCT test.b):Int64]
1001- Aggregate: groupBy=[[test.c]], aggr=[[min(alias2), count(alias1)]] [c:UInt32, min(alias2):UInt32;N, count(alias1):Int64]
1002- Aggregate: groupBy=[[test.c, test.b AS alias1]], aggr=[[min(test.a) AS alias2]] [c:UInt32, alias1:UInt32, alias2:UInt32;N]
1003- TableScan: test [a:UInt32, b:UInt32, c:UInt32]
977+ @"
978+ Aggregate: groupBy=[[test.c]], aggr=[[min(test.a), count(DISTINCT test.b)]] [c:UInt32, min(test.a):UInt32;N, count(DISTINCT test.b):Int64]
979+ TableScan: test [a:UInt32, b:UInt32, c:UInt32]
1004980 "
1005981 )
1006982 }
0 commit comments