1818package org .apache .doris .nereids .rules .rewrite ;
1919
2020import org .apache .doris .common .Pair ;
21- import org .apache .doris .nereids .properties .DataTrait ;
2221import org .apache .doris .nereids .properties .FuncDeps ;
2322import org .apache .doris .nereids .rules .Rule ;
2423import org .apache .doris .nereids .rules .RuleType ;
@@ -125,45 +124,36 @@ public List<Rule> buildRules() {
125124 }
126125
127126 // eliminate the slot of primary plan in agg
127+ // e.g.
128+ // select primary_table_pk, primary_table_other from primary_table join foreign_table on pk = fk
129+ // group by pk, primary_table_other_cols;
128130 private LogicalAggregate <?> eliminatePrimaryOutput (LogicalAggregate <?> agg , Plan child ,
129131 Plan primary , Plan foreign ) {
130132 Set <Slot > aggInputs = agg .getInputSlots ();
131133 if (primary .getOutputSet ().stream ().noneMatch (aggInputs ::contains )) {
132134 return agg ;
133135 }
134136 // Firstly, using fd to eliminate group by key.
135- // group by primary_table_pk, primary_table_other
136- // -> group by primary_table_pk
137- Set <Set <Slot >> groupBySlots = new HashSet <>();
138- Set <Slot > validSlots = new HashSet <>();
139- for (Expression expression : agg .getGroupByExpressions ()) {
140- groupBySlots .add (expression .getInputSlots ());
141- validSlots .addAll (expression .getInputSlots ());
142- }
143- DataTrait dataTrait = child .getLogicalProperties ().getTrait ();
144- FuncDeps funcDeps = dataTrait .getAllValidFuncDeps (validSlots );
145- Set <Slot > foreignOutput = Sets .intersection (agg .getOutputSet (), foreign .getOutputSet ());
146- Set <Set <Slot >> minGroupBySlots = funcDeps .eliminateDeps (groupBySlots , foreignOutput );
147- Set <Expression > removeExpression = new HashSet <>();
148- for (Set <Slot > slots : groupBySlots ) {
149- if (!minGroupBySlots .contains (slots ) && !foreignOutput .containsAll (slots )) {
150- removeExpression .add (slots .iterator ().next ());
151- }
152- }
137+ // group by pk, primary_table_other_cols;
138+ // -> group by pk;
139+ Set <Expression > removeExpression = EliminateGroupByKey .findCanBeRemovedExpressions (agg ,
140+ Sets .intersection (agg .getOutputSet (), foreign .getOutputSet ()),
141+ child .getLogicalProperties ().getTrait ());
153142 List <Expression > minGroupBySlotList = new ArrayList <>();
154143 for (Expression expression : agg .getGroupByExpressions ()) {
155144 if (!removeExpression .contains (expression )) {
156145 minGroupBySlotList .add (expression );
157146 }
158147 }
159148
160- // Secondly, put bijective slot into map: {primary_table_pk : foreign_table_fk }
149+ // Secondly, put bijective slot into map: {pk : fk }
161150 // Bijective slots are mutually interchangeable within GROUP BY keys.
162- // group by primary_table_pk equals group by foreign_table_fk
151+ // group by pk -> group by fk
163152 Set <Slot > primaryOutputSet = primary .getOutputSet ();
164153 Set <Slot > primarySlots = Sets .intersection (aggInputs , primaryOutputSet );
165154 HashMap <Slot , Slot > primaryToForeignDeps = new HashMap <>();
166- FuncDeps funcDepsForJoin = dataTrait .getAllValidFuncDeps (Sets .union (primaryOutputSet , foreign .getOutputSet ()));
155+ FuncDeps funcDepsForJoin = child .getLogicalProperties ().getTrait ()
156+ .getAllValidFuncDeps (Sets .union (primaryOutputSet , foreign .getOutputSet ()));
167157 for (Slot slot : primarySlots ) {
168158 Set <Set <Slot >> replacedSlotSets = funcDepsForJoin .findBijectionSlots (ImmutableSet .of (slot ));
169159 for (Set <Slot > replacedSlots : replacedSlotSets ) {
@@ -176,6 +166,8 @@ private LogicalAggregate<?> eliminatePrimaryOutput(LogicalAggregate<?> agg, Plan
176166 }
177167
178168 // Thirdly, construct new Agg below join.
169+ // For the pk-fk join, the foreign table side will not expand rows.
170+ // As a result, executing agg(group by fk) before join is same with executing agg(group by fk) after join.
179171 Set <Expression > newGroupBySlots = constructNewGroupBy (minGroupBySlotList , primaryOutputSet ,
180172 primaryToForeignDeps );
181173 List <NamedExpression > newOutput = constructNewOutput (
0 commit comments