risingwave_frontend/optimizer/rule/
agg_group_by_simplify_rule.rs1use risingwave_expr::aggregate::PbAggKind;
16
17use super::prelude::{PlanRef, *};
18use crate::expr::InputRef;
19use crate::optimizer::plan_node::generic::{Agg, GenericPlanRef};
20use crate::optimizer::plan_node::*;
21use crate::utils::{Condition, IndexSet};
22
23pub struct AggGroupBySimplifyRule {}
29impl Rule<Logical> for AggGroupBySimplifyRule {
30 fn apply(&self, plan: PlanRef) -> Option<PlanRef> {
31 let agg: &LogicalAgg = plan.as_logical_agg()?;
32 let (agg_calls, group_key, grouping_sets, agg_input, _two_phase) = agg.clone().decompose();
33 if !grouping_sets.is_empty() {
34 return None;
35 }
36 let functional_dependency = agg_input.functional_dependency();
37 let group_key = group_key.to_vec();
38 if group_key.is_empty() || !functional_dependency.is_key(&group_key) {
39 return None;
40 }
41 let mut minimized_group_key = functional_dependency.minimize_key(&group_key);
42 if minimized_group_key.is_empty() {
46 minimized_group_key.push(group_key[0]);
47 }
48 if minimized_group_key.len() < group_key.len() {
49 let new_group_key = IndexSet::from(minimized_group_key);
50 let new_group_key_len = new_group_key.len();
51 let mut new_agg_calls = vec![];
52 for &i in &group_key {
53 if !new_group_key.contains(i) {
54 let data_type = agg_input.schema().fields[i].data_type();
55 new_agg_calls.push(PlanAggCall {
56 agg_type: PbAggKind::InternalLastSeenValue.into(),
57 return_type: data_type.clone(),
58 inputs: vec![InputRef::new(i, data_type)],
59 distinct: false,
60 order_by: vec![],
61 filter: Condition::true_cond(),
62 direct_args: vec![],
63 });
64 }
65 }
66 new_agg_calls.extend(agg_calls);
67
68 let mut out_fields = vec![];
70 let mut remained_group_key_offset = 0;
71 let mut removed_group_key_offset = new_group_key_len;
72 for &i in &group_key {
73 if new_group_key.contains(i) {
74 out_fields.push(remained_group_key_offset);
75 remained_group_key_offset += 1;
76 } else {
77 out_fields.push(removed_group_key_offset);
78 removed_group_key_offset += 1;
79 }
80 }
81 for i in group_key.len()..agg.base.schema().len() {
82 out_fields.push(i);
83 }
84 let new_agg = Agg::new(new_agg_calls, new_group_key, agg.input());
85
86 Some(LogicalProject::with_out_col_idx(new_agg.into(), out_fields.into_iter()).into())
87 } else {
88 None
89 }
90 }
91}
92
93impl AggGroupBySimplifyRule {
94 pub fn create() -> BoxedRule {
95 Box::new(AggGroupBySimplifyRule {})
96 }
97}