diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/DataTrait.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/DataTrait.java index d5516351ea79e77..7bbbb818e032793 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/DataTrait.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/DataTrait.java @@ -118,6 +118,14 @@ public boolean isUniformAndNotNull(ImmutableSet slotSet) { return true; } + public boolean isUniformAndHasConstValue(Slot slot) { + return uniformSet.isUniformAndHasConstValue(slot); + } + + public Optional getUniformValue(Slot slot) { + return uniformSet.slotUniformValue.get(slot); + } + public boolean isNullSafeEqual(Slot l, Slot r) { return equalSet.isEqual(l, r); } @@ -565,6 +573,10 @@ public boolean isUniformAndNotNull(Slot slot) { && !slotUniformValue.get(slot).get().nullable()); } + public boolean isUniformAndHasConstValue(Slot slot) { + return slotUniformValue.containsKey(slot) && slotUniformValue.get(slot).isPresent(); + } + @Override public String toString() { return "{" + slotUniformValue + "}"; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniform.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniform.java index 31044f71f722987..68e48e1e10bc4f7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniform.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniform.java @@ -30,7 +30,9 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; /** * +--aggregate(group by a,b output a,b,max(c)) @@ -41,7 +43,7 @@ public class EliminateGroupByKeyByUniform extends OneRewriteRuleFactory { @Override public Rule build() { - return logicalAggregate().when(agg -> !agg.getSourceRepeat().isPresent()) + return logicalAggregate().whenNot(agg -> agg.getSourceRepeat().isPresent()) .whenNot(agg -> agg.getGroupByExpressions().isEmpty()) .then(EliminateGroupByKeyByUniform::eliminate) .toRule(RuleType.ELIMINATE_GROUP_BY_KEY_BY_UNIFORM); @@ -51,7 +53,7 @@ public Rule build() { private static Plan eliminate(LogicalAggregate agg) { DataTrait aggChildTrait = agg.child().getLogicalProperties().getTrait(); // Get the Group by column of agg. If there is a uniform one, delete the group by key. - List removedExpression = new ArrayList<>(); + Set removedExpression = new LinkedHashSet<>(); List newGroupBy = new ArrayList<>(); for (Expression groupBy : agg.getGroupByExpressions()) { if (!(groupBy instanceof Slot)) { @@ -64,13 +66,20 @@ private static Plan eliminate(LogicalAggregate agg) { newGroupBy.add(groupBy); } } - // TODO Consider whether there are other opportunities for optimization when newGroupBy is empty + if (removedExpression.isEmpty()) { + return null; + } + // when newGroupBy is empty, need retain one expr in group by, otherwise the result may be wrong in empty table if (newGroupBy.isEmpty()) { + Expression expr = removedExpression.iterator().next(); + newGroupBy.add(expr); + removedExpression.remove(expr); + } + if (removedExpression.isEmpty()) { return null; } - List newOutputs = new ArrayList<>(); - // If this output appears in the removedExpression column, replace it with anyvalue + // If this output appears in the removedExpression column, replace it with any_value for (NamedExpression output : agg.getOutputExpressions()) { if (output instanceof Slot) { if (removedExpression.contains(output)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalProject.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalProject.java index 9539b3f9ee976a6..63845a87db23ad8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalProject.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalProject.java @@ -238,15 +238,16 @@ public void computeUnique(DataTrait.Builder builder) { public void computeUniform(DataTrait.Builder builder) { builder.addUniformSlot(child(0).getLogicalProperties().getTrait()); for (NamedExpression proj : getProjects()) { - if (proj.children().isEmpty()) { + if (!(proj instanceof Alias)) { continue; } if (proj.child(0).isConstant()) { builder.addUniformSlotAndLiteral(proj.toSlot(), proj.child(0)); - } else if (ExpressionUtils.isInjective(proj.child(0))) { - ImmutableSet inputs = ImmutableSet.copyOf(proj.getInputSlots()); - if (child(0).getLogicalProperties().getTrait().isUniform(inputs)) { - builder.addUniformSlot(proj.toSlot()); + } else if (proj.child(0) instanceof Slot) { + Slot slot = (Slot) proj.child(0); + if (child(0).getLogicalProperties().getTrait().isUniformAndHasConstValue(slot)) { + builder.addUniformSlotAndLiteral(proj.toSlot(), + child(0).getLogicalProperties().getTrait().getUniformValue(slot).get()); } } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniformTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniformTest.java index d23e323e1845146..7e5b20b42189cea 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniformTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateGroupByKeyByUniformTest.java @@ -1,3 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + package org.apache.doris.nereids.rules.rewrite; import org.apache.doris.nereids.util.MemoPatternMatchSupported;