This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new 6acf3dad10b branch-4.1: [fix](nereids) Fix DISTINCT aggregate planning
#65368 #65664 #68386 (#70198)
6acf3dad10b is described below
commit 6acf3dad10bd59d4f645ae998734a22199b90013
Author: yujun <[email protected]>
AuthorDate: Tue Nov 10 13:52:16 2026 +0800
branch-4.1: [fix](nereids) Fix DISTINCT aggregate planning #65368 #65664
#68386 (#70198)
cherry-pick: #65368
cherry-pick: #65664
cherry-pick: #68386
---------
Co-authored-by: feiniaofeiafei <[email protected]>
Co-authored-by: Mryange <[email protected]>
---
.../nereids/rules/analysis/NormalizeAggregate.java | 5 +-
.../nereids/rules/analysis/NormalizeRepeat.java | 3 +
.../rules/expression/rules/MedianConvert.java | 2 +-
.../rules/implementation/SplitAggMultiPhase.java | 2 +-
.../SplitAggMultiPhaseWithoutGbyKey.java | 2 +-
.../nereids/rules/rewrite/CheckMultiDistinct.java | 50 +--
.../rules/rewrite/DistinctAggStrategySelector.java | 16 +-
.../rules/rewrite/DistinctAggregateRewriter.java | 67 +++-
.../rules/rewrite/SplitMultiDistinctStrategy.java | 6 +-
.../expressions/functions/agg/CollectList.java | 15 +
.../functions/agg/ExponentialMovingAverage.java | 6 +
.../expressions/functions/agg/GroupBitmapXor.java | 11 +-
.../expressions/functions/agg/GroupConcat.java | 8 +
.../trees/expressions/functions/agg/Histogram.java | 5 +
.../trees/expressions/functions/agg/MapAgg.java | 2 +-
.../trees/expressions/functions/agg/MapAggV2.java | 2 +-
.../functions/agg/MultiDistinctGroupConcat.java | 8 +
.../expressions/functions/agg/Percentile.java | 5 +
.../functions/agg/PercentileApprox.java | 5 +
.../functions/agg/PercentileApproxWeighted.java | 5 +
.../expressions/functions/agg/PercentileArray.java | 5 +
.../functions/agg/PercentileReservoir.java | 5 +
.../trees/expressions/functions/agg/TopN.java | 5 +
.../trees/expressions/functions/agg/TopNArray.java | 5 +
.../expressions/functions/agg/TopNWeighted.java | 5 +
.../apache/doris/nereids/util/AggregateUtils.java | 31 +-
.../rewrite/DistinctAggregateRewriterTest.java | 17 +-
.../agg_function/agg_distinct_function.out | 393 +++++++++++++++++++++
.../agg_strategy/distinct_agg_rewriter.out | 9 +
.../distinct_agg_strategy_selector.out | 15 +
.../test_convert_median_to_percentile.out | 3 +
.../agg_function/agg_distinct_function.groovy | 212 +++++++++++
.../nereids_p0/aggregate/agg_group_concat.groovy | 9 +
.../agg_strategy/distinct_agg_rewriter.groovy | 23 +-
.../distinct_agg_strategy_selector.groovy | 43 +++
.../test_convert_median_to_percentile.groovy | 13 +
.../query_p0/group_concat/test_group_concat.groovy | 2 +-
37 files changed, 925 insertions(+), 95 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeAggregate.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeAggregate.java
index 2cc864192fb..9b46201c7b1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeAggregate.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeAggregate.java
@@ -40,7 +40,6 @@ import
org.apache.doris.nereids.trees.expressions.WindowExpression;
import
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
import org.apache.doris.nereids.trees.expressions.functions.agg.AnyValue;
import org.apache.doris.nereids.trees.expressions.functions.generator.Unnest;
-import org.apache.doris.nereids.trees.expressions.literal.Literal;
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
@@ -181,7 +180,7 @@ public class NormalizeAggregate implements
RewriteRuleFactory, NormalizeToSlot {
for (Expression arg : aggFunc.children()) {
// should not push down literal under aggregate
// e.g. group_concat(distinct xxx, ','), the ',' literal
show stay in aggregate
- if (arg instanceof Literal) {
+ if (arg.isConstant()) {
continue;
}
if (arg.containsType(SubqueryExpr.class,
WindowExpression.class, Unnest.class,
@@ -199,7 +198,7 @@ public class NormalizeAggregate implements
RewriteRuleFactory, NormalizeToSlot {
for (Expression arg : aggFunc.children()) {
// should not push down literal under aggregate
// e.g. group_concat(distinct xxx, ','), the ',' literal
show stay in aggregate
- if (arg instanceof Literal) {
+ if (arg.isConstant()) {
continue;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeRepeat.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeRepeat.java
index 8016bf6f7e7..bbabf96f7f1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeRepeat.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/NormalizeRepeat.java
@@ -241,6 +241,9 @@ public class NormalizeRepeat extends OneAnalysisRuleFactory
{
ImmutableSet.Builder<Expression> argumentsOfAggregateFunctionBuilder =
ImmutableSet.builder();
for (AggregateFunction function : aggregateFunctions) {
for (Expression arg : function.getArguments()) {
+ if (arg.isConstant()) {
+ continue;
+ }
if (arg instanceof OrderExpression) {
argumentsOfAggregateFunctionBuilder.add(arg.child(0));
} else {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/MedianConvert.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/MedianConvert.java
index e6e295ef98c..d8144bf2508 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/MedianConvert.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/MedianConvert.java
@@ -39,7 +39,7 @@ public class MedianConvert implements
ExpressionPatternRuleFactory {
public List<ExpressionPatternMatcher<? extends Expression>> buildRules() {
return ImmutableList.of(
matchesType(Median.class).then(median ->
- new Percentile(median.child(0), DoubleLiteral.of(0.5))
+ new Percentile(median.isDistinct(), median.child(0),
DoubleLiteral.of(0.5))
).toRule(ExpressionRuleType.MEDIAN_CONVERT)
);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhase.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhase.java
index 9a5b9ad412a..390c3af6e04 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhase.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhase.java
@@ -76,7 +76,7 @@ public class SplitAggMultiPhase extends SplitAggBaseRule
implements Implementati
return ImmutableList.of(
logicalAggregate()
.when(agg -> !agg.getGroupByExpressions().isEmpty())
- .when(agg -> agg.getDistinctArguments().size() == 1 ||
agg.distinctFuncNum() == 1)
+ .when(agg ->
AggregateUtils.distinctArgumentGroupCountUpToTwo(agg) == 1)
.thenApplyMulti(this::rewrite)
.toRule(RuleType.SPLIT_AGG_MULTI_PHASE)
);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhaseWithoutGbyKey.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhaseWithoutGbyKey.java
index 294777a900a..be7666544ee 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhaseWithoutGbyKey.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/SplitAggMultiPhaseWithoutGbyKey.java
@@ -75,7 +75,7 @@ public class SplitAggMultiPhaseWithoutGbyKey extends
SplitAggBaseRule implements
return ImmutableList.of(
logicalAggregate()
.when(agg -> agg.getGroupByExpressions().isEmpty())
- .when(agg -> agg.getDistinctArguments().size() == 1 ||
agg.distinctFuncNum() == 1)
+ .when(agg ->
AggregateUtils.distinctArgumentGroupCountUpToTwo(agg) == 1)
.thenApplyMulti(ctx -> rewrite(ctx.root,
ctx.cascadesContext))
.toRule(RuleType.SPLIT_AGG_MULTI_PHASE_WITHOUT_GBY_KEY)
);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMultiDistinct.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMultiDistinct.java
index d9c953444ba..0f23dcd1a7d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMultiDistinct.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/CheckMultiDistinct.java
@@ -20,20 +20,12 @@ package org.apache.doris.nereids.rules.rewrite;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.rules.Rule;
import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.trees.expressions.OrderExpression;
-import
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
-import
org.apache.doris.nereids.trees.expressions.functions.agg.SupportMultiDistinct;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.nereids.util.AggregateUtils;
/**
- * If there are multiple distinct aggregate functions that cannot
- * be transformed into multi_distinct, an error is reported.
- * The following functions can be transformed into multi_distinct:
- * - count -> MULTI_DISTINCT_COUNT
- * - sum -> MULTI_DISTINCT_SUM
- * - avg -> MULTI_DISTINCT_AVG
- * - group_concat -> MULTI_DISTINCT_GROUP_CONCAT
+ * Check that previous aggregate rewrite rules have already handled multiple
distinct argument groups.
*/
public class CheckMultiDistinct extends OneRewriteRuleFactory {
@Override
@@ -42,43 +34,9 @@ public class CheckMultiDistinct extends
OneRewriteRuleFactory {
}
private LogicalAggregate checkDistinct(LogicalAggregate<? extends Plan>
aggregate) {
- if (aggregate.getDistinctArguments().size() > 1) {
-
- for (AggregateFunction func : aggregate.getAggregateFunctions()) {
- if (func.isDistinct() && !(func instanceof
SupportMultiDistinct)) {
- throw new AnalysisException(func.toString() + " can't
support multi distinct.");
- }
- }
- }
-
- boolean distinctMultiColumns = false;
- for (AggregateFunction func : aggregate.getAggregateFunctions()) {
- if (!func.isDistinct()) {
- continue;
- }
- if (func.arity() <= 1) {
- continue;
- }
- for (int i = 1; i < func.arity(); i++) {
- if (!func.child(i).getInputSlots().isEmpty() &&
!(func.child(i) instanceof OrderExpression)) {
- // think about group_concat(distinct col_1, ',')
- distinctMultiColumns = true;
- break;
- }
- }
- if (distinctMultiColumns) {
- break;
- }
- }
-
- long distinctFunctionNum = 0;
- for (AggregateFunction aggregateFunction :
aggregate.getAggregateFunctions()) {
- distinctFunctionNum += aggregateFunction.isDistinct() ? 1 : 0;
- }
-
- if (distinctMultiColumns && distinctFunctionNum > 1) {
+ if (AggregateUtils.distinctArgumentGroupCountUpToTwo(aggregate) > 1) {
throw new AnalysisException(
- "The query contains multi count distinct or sum distinct,
each can't have multi columns");
+ "Multiple DISTINCT aggregate functions with different
argument lists are not supported.");
}
return aggregate;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggStrategySelector.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggStrategySelector.java
index de83915c843..1ff8efc0341 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggStrategySelector.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggStrategySelector.java
@@ -103,11 +103,12 @@ public class DistinctAggStrategySelector extends
DefaultPlanRewriter<DistinctSel
// not process:
// count(distinct a,b);
// count(distinct a), sum(distinct a);
+ // count(distinct a,b), count(distinct b,a);
// count(distinct a)
// process:
// count(distinct a,b), count(distinct a,c)
// count(distinct a), sum(distinct b)
- if (agg.distinctFuncNum() < 2 || agg.getDistinctArguments().size() <
2) {
+ if (AggregateUtils.distinctArgumentGroupCountUpToTwo(agg) <= 1) {
return agg;
}
if (shouldUseMultiDistinct(agg)) {
@@ -118,19 +119,20 @@ public class DistinctAggStrategySelector extends
DefaultPlanRewriter<DistinctSel
}
private boolean shouldUseMultiDistinct(LogicalAggregate<? extends Plan>
agg) {
- boolean mustUseCte =
AggregateUtils.containsCountDistinctMultiExpr(agg);
+ boolean mustUseCte =
AggregateUtils.containsNotSupportMultiDistinctFunction(agg);
boolean mustUseMulti = agg.getSourceRepeat().isPresent();
if (mustUseCte && mustUseMulti) {
throw new AnalysisException(
- "Unsupported query: GROUPING SETS/ROLLUP/CUBE cannot be
used with a combination of "
- + "multi-column COUNT(DISTINCT) and other COUNT(DISTINCT)
expressions.\n\n"
+ "Unsupported query: GROUPING SETS/ROLLUP/CUBE cannot be
used with multiple DISTINCT "
+ + "argument groups when any DISTINCT aggregate does not
support multi-distinct execution.\n\n"
+ "Unsupported scenarios:\n"
+ + "• ARRAY_AGG(DISTINCT a) with ARRAY_AGG(DISTINCT b) +
GROUPING\n"
+ "• COUNT(DISTINCT a, b) with COUNT(DISTINCT a) +
GROUPING\n"
+ "• COUNT(DISTINCT a, b) with COUNT(DISTINCT a, c) +
GROUPING\n\n"
+ "Supported scenarios:\n"
- + "• Single COUNT(DISTINCT a, b) + GROUPING\n"
- + "• Multiple COUNT(DISTINCT single_column) + "
- + "GROUPING (e.g., COUNT(DISTINCT a), COUNT(DISTINCT b))");
+ + "• A single DISTINCT argument group with GROUPING\n"
+ + "• Multiple DISTINCT argument groups when all DISTINCT
aggregates support "
+ + "multi-distinct execution (e.g., COUNT(DISTINCT a),
COUNT(DISTINCT b))");
}
if (mustUseCte) {
return false;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriter.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriter.java
index 832641add2d..b6eb9470615 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriter.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriter.java
@@ -21,6 +21,7 @@ import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DistributionInfo;
import org.apache.doris.catalog.HashDistributionInfo;
import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.rules.Rule;
import org.apache.doris.nereids.rules.RuleType;
import org.apache.doris.nereids.rules.rewrite.StatsDerive.DeriveContext;
@@ -83,6 +84,13 @@ public class DistinctAggregateRewriter implements
RewriteRuleFactory {
private static final Set<Class<? extends AggregateFunction>>
supportSplitOtherFunctions = ImmutableSet.of(
Sum.class, Min.class, Max.class, Count.class, Sum0.class,
AnyValue.class);
+ enum Strategy {
+ SPLIT_IN_REWRITE, MULTI_STRATEGY, SPLIT_IN_CASCADES
+ }
+
+ private static final String errorString = "Unsupported query:
GROUP_CONCAT(DISTINCT ... ORDER BY ...)"
+ + " cannot be used together with a multi-argument COUNT(DISTINCT
...).";
+
@Override
public List<Rule> buildRules() {
return ImmutableList.of(
@@ -92,25 +100,41 @@ public class DistinctAggregateRewriter implements
RewriteRuleFactory {
.thenApply(ctx -> rewrite(ctx.root,
ctx.connectContext))
.toRule(RuleType.DISTINCT_AGGREGATE_SPLIT),
logicalAggregate()
- .when(agg -> agg.getGroupByExpressions().isEmpty()
- && agg.mustUseMultiDistinctAgg() &&
!AggregateUtils.containsCountDistinctMultiExpr(agg))
- .then(this::convertToMultiDistinct)
+ .when(agg -> agg.getGroupByExpressions().isEmpty() &&
agg.mustUseMultiDistinctAgg())
+ .then(agg -> {
+ // count(distinct a,b) cannot use multi_distinct
+ if
(AggregateUtils.containsCountDistinctMultiExpr(agg)) {
+ throw new AnalysisException(errorString);
+ }
+ return convertToMultiDistinct(agg);
+ })
.toRule(RuleType.PROCESS_SCALAR_AGG_MUST_USE_MULTI_DISTINCT)
);
}
@VisibleForTesting
- boolean shouldUseMultiDistinct(LogicalAggregate<? extends Plan> aggregate)
{
+ Strategy chooseStrategy(LogicalAggregate<? extends Plan> aggregate) {
// count(distinct a,b) cannot use multi_distinct
- if (AggregateUtils.containsCountDistinctMultiExpr(aggregate)) {
- return false;
- }
- if (aggregate.mustUseMultiDistinctAgg()) {
- return true;
+ boolean mustSplit =
AggregateUtils.containsCountDistinctMultiExpr(aggregate);
+ boolean mustUseMulti = aggregate.mustUseMultiDistinctAgg();
+ if (mustSplit && mustUseMulti) {
+ throw new AnalysisException(errorString);
}
ConnectContext ctx = ConnectContext.get();
+ if (mustSplit) {
+ if (ctx.getSessionVariable().aggPhase == 3 ||
ctx.getSessionVariable().aggPhase == 4) {
+ return Strategy.SPLIT_IN_CASCADES;
+ }
+ return Strategy.SPLIT_IN_REWRITE;
+ }
+ if (mustUseMulti) {
+ return Strategy.MULTI_STRATEGY;
+ }
if (ctx.getSessionVariable().aggPhase == 1 ||
ctx.getSessionVariable().aggPhase == 2) {
- return true;
+ return Strategy.MULTI_STRATEGY;
+ }
+ if (ctx.getSessionVariable().aggPhase == 3 ||
ctx.getSessionVariable().aggPhase == 4) {
+ return Strategy.SPLIT_IN_CASCADES;
}
if (aggregate.getStats() == null || aggregate.child().getStats() ==
null) {
StatsDerive derive = new StatsDerive(false);
@@ -120,12 +144,12 @@ public class DistinctAggregateRewriter implements
RewriteRuleFactory {
Statistics aggChildStats = aggregate.child().getStats();
Set<Expression> dstArgs = aggregate.getDistinctArguments();
if (isDistinctKeySatisfyDistribution(aggregate)) {
- return false;
+ return Strategy.SPLIT_IN_REWRITE;
}
// has unknown statistics, split to bottom and top agg
if
(AggregateUtils.hasUnknownStatistics(aggregate.getGroupByExpressions(),
aggChildStats)
|| AggregateUtils.hasUnknownStatistics(dstArgs,
aggChildStats)) {
- return true;
+ return Strategy.MULTI_STRATEGY;
}
double gbyNdv = aggStats.getRowCount();
@@ -138,8 +162,12 @@ public class DistinctAggregateRewriter implements
RewriteRuleFactory {
double inputRows = aggChildStats.getRowCount();
// group by key ndv is low, distinct key ndv is high, multi_distinct
is better
// otherwise split to bottom and top agg
- return gbyNdv < inputRows * AggregateUtils.LOW_CARDINALITY_THRESHOLD
- && dstNdv > inputRows *
AggregateUtils.HIGH_CARDINALITY_THRESHOLD;
+ if (gbyNdv < inputRows * AggregateUtils.LOW_CARDINALITY_THRESHOLD
+ && dstNdv > inputRows *
AggregateUtils.HIGH_CARDINALITY_THRESHOLD) {
+ return Strategy.MULTI_STRATEGY;
+ } else {
+ return Strategy.SPLIT_IN_REWRITE;
+ }
}
private boolean isDistinctKeySatisfyDistribution(LogicalAggregate<?
extends Plan> aggregate) {
@@ -249,14 +277,15 @@ public class DistinctAggregateRewriter implements
RewriteRuleFactory {
if (aggregate.distinctFuncNum() == 0) {
return null;
}
- if (ctx.getSessionVariable().aggPhase == 3 ||
ctx.getSessionVariable().aggPhase == 4) {
- return null;
- }
- if (shouldUseMultiDistinct(aggregate)) {
+ Strategy strategy = chooseStrategy(aggregate);
+ if (strategy == Strategy.MULTI_STRATEGY) {
return convertToMultiDistinct(aggregate);
- } else {
+ } else if (strategy == Strategy.SPLIT_IN_REWRITE) {
return splitDistinctAgg(aggregate);
+ } else if (strategy == Strategy.SPLIT_IN_CASCADES) {
+ return null;
}
+ return null;
}
private Plan convertToMultiDistinct(LogicalAggregate<? extends Plan>
aggregate) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SplitMultiDistinctStrategy.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SplitMultiDistinctStrategy.java
index c9585d269aa..f05be0a1d11 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SplitMultiDistinctStrategy.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SplitMultiDistinctStrategy.java
@@ -43,6 +43,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -166,10 +167,11 @@ public class SplitMultiDistinctStrategy {
List<List<Alias>> aliases, List<Alias> otherAggFuncs) {
Map<Set<Expression>, List<Alias>> distinctArgToAliasList = new
LinkedHashMap<>();
for (NamedExpression namedExpression : agg.getOutputExpressions()) {
- if (!(namedExpression instanceof Alias) ||
!(namedExpression.child(0) instanceof AggregateFunction)) {
+ if (!(namedExpression instanceof Alias) ||
!namedExpression.containsType(AggregateFunction.class)) {
continue;
}
- AggregateFunction aggFunc = (AggregateFunction)
namedExpression.child(0);
+ Optional<Expression> op = namedExpression.collectFirst(e -> e
instanceof AggregateFunction);
+ AggregateFunction aggFunc = (AggregateFunction) op.get();
if (aggFunc.isDistinct()) {
distinctArgToAliasList.computeIfAbsent(ImmutableSet.copyOf(aggFunc.getDistinctArguments()),
k -> new ArrayList<>()).add((Alias) namedExpression);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
index 6866e23a22e..6c447a22b6d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/CollectList.java
@@ -18,6 +18,7 @@
package org.apache.doris.nereids.trees.expressions.functions.agg;
import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral;
@@ -102,4 +103,18 @@ public class CollectList extends
NotNullableAggregateFunction
public Expression resultForEmptyInput() {
return new ArrayLiteral(new ArrayList<>(), this.getDataType());
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
+
+ @Override
+ public void checkLegalityBeforeTypeCoercion() {
+ if (arity() == 2 && !getArgument(1).isConstant()) {
+ throw new AnalysisException(
+ "collect_list requires second parameter must be a
constant: "
+ + this.toSql());
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
index caeb3b82dc7..7ceda4cf912 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/ExponentialMovingAverage.java
@@ -119,4 +119,10 @@ public class ExponentialMovingAverage extends
NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(1), getArgument(2)) :
ImmutableList.of();
+ }
+
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
index 202a469fdd4..f276f935048 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupBitmapXor.java
@@ -18,6 +18,7 @@
package org.apache.doris.nereids.trees.expressions.functions.agg;
import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
@@ -55,8 +56,7 @@ public class GroupBitmapXor extends NullableAggregateFunction
}
private GroupBitmapXor(boolean distinct, boolean alwaysNullable,
Expression arg0) {
- /* distinct is meaningless to bitmap */
- super("group_bitmap_xor", false, alwaysNullable, arg0);
+ super("group_bitmap_xor", distinct, alwaysNullable, arg0);
}
/** constructor for withChildren and reuse signature */
@@ -92,4 +92,11 @@ public class GroupBitmapXor extends NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public void checkLegalityBeforeTypeCoercion() {
+ if (distinct) {
+ throw new AnalysisException("group_bitmap_xor does not support
DISTINCT");
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupConcat.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupConcat.java
index 8003d687380..1d1205aea8c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupConcat.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/GroupConcat.java
@@ -201,4 +201,12 @@ public class GroupConcat extends NullableAggregateFunction
}
return firstOrderExrIndex;
}
+
+ @Override
+ public void checkLegalityBeforeTypeCoercion() {
+ if (nonOrderArguments == 2 && !getArgument(1).isConstant()) {
+ throw new AnalysisException(
+ "group_concat requires separator must be a constant : " +
this.toSql());
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
index 26e02959243..01486ff2bd6 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Histogram.java
@@ -113,4 +113,9 @@ public class Histogram extends NotNullableAggregateFunction
public Expression resultForEmptyInput() {
return new VarcharLiteral("{\"num_buckets\":0,\"buckets\":[]}");
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAgg.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAgg.java
index c611ced6fb4..9e57a17c560 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAgg.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAgg.java
@@ -54,7 +54,7 @@ public class MapAgg extends NotNullableAggregateFunction
/**
* constructor with 2 arguments.
*/
- private MapAgg(boolean distinct, Expression arg0, Expression arg1) {
+ public MapAgg(boolean distinct, Expression arg0, Expression arg1) {
super("map_agg_v1", distinct, arg0, arg1);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggV2.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggV2.java
index de099933eea..22093016601 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggV2.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MapAggV2.java
@@ -54,7 +54,7 @@ public class MapAggV2 extends NotNullableAggregateFunction
/**
* constructor with 2 arguments.
*/
- private MapAggV2(boolean distinct, Expression arg0, Expression arg1) {
+ public MapAggV2(boolean distinct, Expression arg0, Expression arg1) {
super("map_agg_v2", distinct, arg0, arg1);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctGroupConcat.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctGroupConcat.java
index 5fc78899a72..8f1f6debe80 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctGroupConcat.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/MultiDistinctGroupConcat.java
@@ -140,4 +140,12 @@ public class MultiDistinctGroupConcat extends
NullableAggregateFunction
}
return firstOrderExrIndex;
}
+
+ @Override
+ public void checkLegalityBeforeTypeCoercion() {
+ if (nonOrderArguments == 2 && !getArgument(1).isConstant()) {
+ throw new AnalysisException(
+ "multi_distinct_group_concat requires separator must be a
constant : " + this.toSql());
+ }
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
index 41d85424f8e..16a2821a541 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Percentile.java
@@ -107,4 +107,9 @@ public class Percentile extends NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
index d889f588df6..3e0229a1234 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApprox.java
@@ -121,4 +121,9 @@ public class PercentileApprox extends
NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
index 86e3f40c781..2eae91d865b 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileApproxWeighted.java
@@ -125,4 +125,9 @@ public class PercentileApproxWeighted extends
NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0), getArgument(1)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
index 560d1003383..89e8dded9a5 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileArray.java
@@ -111,4 +111,9 @@ public class PercentileArray extends
NotNullableAggregateFunction
public Expression resultForEmptyInput() {
return new ArrayLiteral(new ArrayList<>(), this.getDataType());
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
index 7c6f7bb6652..5e91e794064 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/PercentileReservoir.java
@@ -107,4 +107,9 @@ public class PercentileReservoir extends
NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
index b223b130cc0..f03bbedf343 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopN.java
@@ -134,4 +134,9 @@ public class TopN extends NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
index bc370be9619..840f520b876 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNArray.java
@@ -137,4 +137,9 @@ public class TopNArray extends NullableAggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
index 9297e7f1ae0..9d3152685a4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/TopNWeighted.java
@@ -219,4 +219,9 @@ public class TopNWeighted extends NullableAggregateFunction
+ this.toSql());
}
}
+
+ @Override
+ public List<Expression> getDistinctArguments() {
+ return distinct ? ImmutableList.of(getArgument(0), getArgument(1)) :
ImmutableList.of();
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/AggregateUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/AggregateUtils.java
index 067bd734467..6e5e0068408 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/AggregateUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/AggregateUtils.java
@@ -29,6 +29,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.agg.SupportMultiDist
import org.apache.doris.nereids.trees.expressions.functions.scalar.If;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.algebra.Aggregate;
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.statistics.ColumnStatistic;
@@ -134,6 +135,34 @@ public class AggregateUtils {
expr instanceof Count && ((Count) expr).isDistinct() &&
expr.arity() > 1);
}
+ /** e.g. Aggregation with avg(distinct a)(not support multiDistinct) or
count(distinct a,b) will return true*/
+ public static boolean
containsNotSupportMultiDistinctFunction(LogicalAggregate<? extends Plan>
aggregate) {
+ return ExpressionUtils.deapAnyMatch(aggregate.getOutputExpressions(),
expr -> {
+ if (expr instanceof AggregateFunction && ((AggregateFunction)
expr).isDistinct()) {
+ return !(expr instanceof SupportMultiDistinct)
+ || expr instanceof Count && ((Count)
expr).isDistinct() && expr.arity() > 1;
+ }
+ return false;
+ });
+ }
+
+ /** count agg function distinct group, up to 2*/
+ public static int distinctArgumentGroupCountUpToTwo(Aggregate<? extends
Plan> aggregate) {
+ Set<Expression> distinctArgumentGroup = null;
+ for (AggregateFunction aggregateFunction :
aggregate.getAggregateFunctions()) {
+ if (!aggregateFunction.isDistinct()) {
+ continue;
+ }
+ Set<Expression> currentGroup =
ImmutableSet.copyOf(aggregateFunction.getDistinctArguments());
+ if (distinctArgumentGroup == null) {
+ distinctArgumentGroup = currentGroup;
+ } else if (!distinctArgumentGroup.equals(currentGroup)) {
+ return 2;
+ }
+ }
+ return distinctArgumentGroup == null ? 0 : 1;
+ }
+
/**getAllKeySet*/
public static Set<NamedExpression> getAllKeySet(LogicalAggregate<? extends
Plan> aggregate) {
Set<NamedExpression> distinctArguments =
getDistinctNamedExpr(aggregate);
@@ -156,7 +185,7 @@ public class AggregateUtils {
public static Set<NamedExpression> getDistinctNamedExpr(LogicalAggregate<?
extends Plan> aggregate) {
return aggregate.getAggregateFunctions().stream()
.filter(AggregateFunction::isDistinct)
- .flatMap(aggFunc -> aggFunc.getArguments().stream())
+ .flatMap(aggFunc -> aggFunc.getDistinctArguments().stream())
.filter(NamedExpression.class::isInstance)
.map(NamedExpression.class::cast)
.collect(ImmutableSet.toImmutableSet());
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriterTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriterTest.java
index 7b9e957b742..dac2395c17f 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriterTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/DistinctAggregateRewriterTest.java
@@ -20,6 +20,7 @@ package org.apache.doris.nereids.rules.rewrite;
import org.apache.doris.catalog.DistributionInfo;
import org.apache.doris.catalog.HashDistributionInfo;
import
org.apache.doris.nereids.rules.analysis.LogicalSubQueryAliasToLogicalProject;
+import
org.apache.doris.nereids.rules.rewrite.DistinctAggregateRewriter.Strategy;
import org.apache.doris.nereids.trees.expressions.SlotReference;
import
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
@@ -94,8 +95,8 @@ public class DistinctAggregateRewriterTest extends
TestWithFeService implements
private void applyMock() {
new MockUp<DistinctAggregateRewriter>() {
@Mock
- boolean shouldUseMultiDistinct(LogicalAggregate<? extends Plan>
aggregate) {
- return false;
+ Strategy chooseStrategy(LogicalAggregate<? extends Plan>
aggregate) {
+ return Strategy.SPLIT_IN_REWRITE;
}
};
}
@@ -249,7 +250,7 @@ public class DistinctAggregateRewriterTest extends
TestWithFeService implements
}
@Test
- void testShouldUseMultiDistinctWithoutStatsSatisfyDistribution() throws
Exception {
+ void testChooseStrategyWithoutStatsSatisfyDistribution() throws Exception {
DistinctAggregateRewriter rewriter =
DistinctAggregateRewriter.INSTANCE;
LogicalAggregate<? extends Plan> aggregate = getLogicalAggregate(
"select bb, count(distinct aa) from "
@@ -265,11 +266,11 @@ public class DistinctAggregateRewriterTest extends
TestWithFeService implements
((AbstractPlan) child).setStatistics(new Statistics(10000, colStats));
aggregate.setStatistics(new Statistics(100, ImmutableMap.of()));
- Assertions.assertFalse(rewriter.shouldUseMultiDistinct(aggregate));
+ Assertions.assertEquals(Strategy.SPLIT_IN_REWRITE,
rewriter.chooseStrategy(aggregate));
}
@Test
- void testShouldUseMultiDistinctWithStatsSelected() throws Exception {
+ void testChooseStrategyWithStatsSelected() throws Exception {
DistinctAggregateRewriter rewriter = new DistinctAggregateRewriter();
LogicalAggregate<? extends Plan> aggregate = getLogicalAggregate(
"select b, count(distinct a) from test.distinct_agg_split_t
group by b"
@@ -283,11 +284,11 @@ public class DistinctAggregateRewriterTest extends
TestWithFeService implements
((AbstractPlan) child).setStatistics(new Statistics(100000, colStats));
aggregate.setStatistics(new Statistics(240, ImmutableMap.of()));
- Assertions.assertFalse(rewriter.shouldUseMultiDistinct(aggregate));
+ Assertions.assertEquals(Strategy.SPLIT_IN_REWRITE,
rewriter.chooseStrategy(aggregate));
}
@Test
- void testShouldUseMultiDistinctWithPartitionTable() {
+ void testChooseStrategyWithPartitionTable() {
DistinctAggregateRewriter rewriter =
DistinctAggregateRewriter.INSTANCE;
LogicalAggregate<? extends Plan> aggregate = getLogicalAggregate(
"select count(distinct record_id) from sales_records group by
sale_date;"
@@ -301,7 +302,7 @@ public class DistinctAggregateRewriterTest extends
TestWithFeService implements
((AbstractPlan) child).setStatistics(new Statistics(10000, colStats));
aggregate.setStatistics(new Statistics(100, ImmutableMap.of()));
- Assertions.assertTrue(rewriter.shouldUseMultiDistinct(aggregate));
+ Assertions.assertEquals(Strategy.MULTI_STRATEGY,
rewriter.chooseStrategy(aggregate));
}
@Test
diff --git
a/regression-test/data/nereids_function_p0/agg_function/agg_distinct_function.out
b/regression-test/data/nereids_function_p0/agg_function/agg_distinct_function.out
new file mode 100644
index 00000000000..e3c944e1365
--- /dev/null
+++
b/regression-test/data/nereids_function_p0/agg_function/agg_distinct_function.out
@@ -0,0 +1,393 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !array_agg --
+[1, 2, 3, 4, 5]
+
+-- !array_agg_group --
+1 [1, 2, 3]
+2 [1, 4, 5]
+
+-- !avg --
+3.0
+
+-- !avg_group --
+1 2.0
+2 3.333333333333333
+
+-- !avg_weighted --
+3.666666666666667
+
+-- !avg_weighted_group --
+1 2.333333333333333
+2 4.2
+
+-- !collect_list --
+[1, 2, 3, 4, 5]
+
+-- !collect_list_group --
+1 [1, 2, 3]
+2 [1, 4, 5]
+
+-- !collect_set --
+[1, 2, 3, 4, 5]
+
+-- !collect_set_group --
+1 [1, 2, 3]
+2 [1, 4, 5]
+
+-- !corr_welford --
+1.0
+
+-- !corr_welford_group --
+1 1.0
+2 1.0
+
+-- !corr --
+1.0
+
+-- !corr_group --
+1 1.0
+2 1.0
+
+-- !covar --
+20.0
+
+-- !covar_group --
+1 6.666666666666664
+2 28.88888888888889
+
+-- !covar_samp --
+25.0
+
+-- !covar_samp_group --
+1 10.0
+2 43.33333333333334
+
+-- !group_bit_and --
+0
+
+-- !group_bit_and_group --
+1 0
+2 0
+
+-- !group_bit_or --
+7
+
+-- !group_bit_or_group --
+1 3
+2 5
+
+-- !group_bit_xor --
+1
+
+-- !group_bit_xor_group --
+1 0
+2 0
+
+-- !group_concat --
+a,b,c,d,e
+
+-- !group_concat_group --
+1 a,b,c
+2 a,d,e
+
+-- !histogram --
+{"num_buckets":5,"buckets":[{"lower":"1","upper":"1","ndv":1,"count":1,"pre_sum":0},{"lower":"2","upper":"2","ndv":1,"count":1,"pre_sum":1},{"lower":"3","upper":"3","ndv":1,"count":1,"pre_sum":2},{"lower":"4","upper":"4","ndv":1,"count":1,"pre_sum":3},{"lower":"5","upper":"5","ndv":1,"count":1,"pre_sum":4}]}
+
+-- !histogram_group --
+1
{"num_buckets":3,"buckets":[{"lower":"1","upper":"1","ndv":1,"count":1,"pre_sum":0},{"lower":"2","upper":"2","ndv":1,"count":1,"pre_sum":1},{"lower":"3","upper":"3","ndv":1,"count":1,"pre_sum":2}]}
+2
{"num_buckets":3,"buckets":[{"lower":"1","upper":"1","ndv":1,"count":1,"pre_sum":0},{"lower":"4","upper":"4","ndv":1,"count":1,"pre_sum":1},{"lower":"5","upper":"5","ndv":1,"count":1,"pre_sum":2}]}
+
+-- !hll_raw_agg --
+5
+
+-- !hll_raw_agg_group --
+1 3
+2 3
+
+-- !hll_union_agg --
+5
+
+-- !hll_union_agg_group --
+1 3
+2 3
+
+-- !kurt --
+-1.3
+
+-- !kurt_group --
+1 -1.5
+2 -1.499999999999995
+
+-- !map_agg_group --
+[1, 2, 3] ["a", "b", "c"]
+[1, 4, 5] ["a", "d", "e"]
+
+-- !map_agg --
+[1, 2, 3, 4, 5] ["a", "b", "c", "d", "e"]
+
+-- !max_by --
+e
+
+-- !max_by_group --
+1 c
+2 e
+
+-- !min_by --
+a
+
+-- !min_by_group --
+1 a
+2 a
+
+-- !percentile --
+3.0
+
+-- !percentile_group --
+1 2.0
+2 4.0
+
+-- !percentile_approx --
+3.0
+
+-- !percentile_approx_group --
+1 2.0
+2 4.0
+
+-- !percentile_array --
+[2, 3, 4]
+
+-- !percentile_array_group --
+1 [1.5, 2, 2.5]
+2 [2.5, 4, 4.5]
+
+-- !percentile_approx_weighted --
+3.857142925262451
+
+-- !percentile_approx_weighted_group --
+1 2.400000095367432
+2 4.44444465637207
+
+-- !topn --
+{"e":1,"d":1,"c":1}
+
+-- !topn_group --
+1 {"c":1,"b":1,"a":1}
+2 {"e":1,"d":1,"a":1}
+
+-- !topn_array --
+["e", "d", "c"]
+
+-- !topn_array_group --
+1 ["c", "b", "a"]
+2 ["e", "d", "a"]
+
+-- !topn_weighted --
+["e", "d", "c"]
+
+-- !topn_weighted_group --
+1 ["c", "b", "a"]
+2 ["e", "d", "a"]
+
+-- !two_distinct_functions --
+[1, 2, 3, 4, 5] [10, 20, 30, 40, 50]
+
+-- !two_distinct_functions_group --
+1 [1, 2, 3] [10, 20, 30]
+2 [1, 4, 5] [10, 40, 50]
+
+-- !two_avg --
+3.0 30.0
+
+-- !two_avg_group --
+1 2.0 20.0
+2 3.333333333333333 33.33333333333334
+
+-- !two_avg_weighted --
+3.666666666666667 36.66666666666666
+
+-- !two_avg_weighted_group --
+1 2.333333333333333 23.33333333333333
+2 4.2 42.0
+
+-- !two_collect_list --
+[1, 2, 3, 4, 5] [10, 20, 30, 40, 50]
+
+-- !two_collect_list_group --
+1 [1, 2, 3] [10, 20, 30]
+2 [1, 4, 5] [10, 40, 50]
+
+-- !two_collect_set --
+[1, 2, 3, 4, 5] [10, 20, 30, 40, 50]
+
+-- !two_collect_set_group --
+1 [1, 2, 3] [10, 20, 30]
+2 [1, 4, 5] [10, 40, 50]
+
+-- !two_corr_welford --
+0.9999999999999999 1.0
+
+-- !two_corr_welford_group --
+1 1.0 1.0
+2 1.0 1.0
+
+-- !two_corr --
+1.0 1.0
+
+-- !two_corr_group --
+1 1.0 1.0
+2 1.0 1.0
+
+-- !two_covar --
+20.0 2.0
+
+-- !two_covar_group --
+1 6.666666666666664 0.666666666666667
+2 28.88888888888889 2.888888888888889
+
+-- !two_covar_samp --
+25.0 2.5
+
+-- !two_covar_samp_group --
+1 10.0 1.0
+2 43.33333333333334 4.333333333333332
+
+-- !two_group_bit_and --
+0 0
+
+-- !two_group_bit_and_group --
+1 0 0
+2 0 0
+
+-- !two_group_bit_or --
+7 62
+
+-- !two_group_bit_or_group --
+1 3 30
+2 5 58
+
+-- !two_group_bit_xor --
+1 26
+
+-- !two_group_bit_xor_group --
+1 0 0
+2 0 16
+
+-- !two_group_concat --
+a,b,c,d,e 1,2,3,4,5
+
+-- !two_group_concat_group --
+1 a,b,c 1,2,3
+2 a,d,e 1,4,5
+
+-- !two_histogram --
+{"num_buckets":5,"buckets":[{"lower":"1","upper":"1","ndv":1,"count":1,"pre_sum":0},{"lower":"2","upper":"2","ndv":1,"count":1,"pre_sum":1},{"lower":"3","upper":"3","ndv":1,"count":1,"pre_sum":2},{"lower":"4","upper":"4","ndv":1,"count":1,"pre_sum":3},{"lower":"5","upper":"5","ndv":1,"count":1,"pre_sum":4}]}
{"num_buckets":5,"buckets":[{"lower":"10","upper":"10","ndv":1,"count":1,"pre_sum":0},{"lower":"20","upper":"20","ndv":1,"count":1,"pre_sum":1},{"lower":"30","upper":"30","ndv":1,"co
[...]
+
+-- !two_histogram_group --
+1
{"num_buckets":3,"buckets":[{"lower":"1","upper":"1","ndv":1,"count":1,"pre_sum":0},{"lower":"2","upper":"2","ndv":1,"count":1,"pre_sum":1},{"lower":"3","upper":"3","ndv":1,"count":1,"pre_sum":2}]}
{"num_buckets":3,"buckets":[{"lower":"10","upper":"10","ndv":1,"count":1,"pre_sum":0},{"lower":"20","upper":"20","ndv":1,"count":1,"pre_sum":1},{"lower":"30","upper":"30","ndv":1,"count":1,"pre_sum":2}]}
+2
{"num_buckets":3,"buckets":[{"lower":"1","upper":"1","ndv":1,"count":1,"pre_sum":0},{"lower":"4","upper":"4","ndv":1,"count":1,"pre_sum":1},{"lower":"5","upper":"5","ndv":1,"count":1,"pre_sum":2}]}
{"num_buckets":3,"buckets":[{"lower":"10","upper":"10","ndv":1,"count":1,"pre_sum":0},{"lower":"40","upper":"40","ndv":1,"count":1,"pre_sum":1},{"lower":"50","upper":"50","ndv":1,"count":1,"pre_sum":2}]}
+
+-- !two_hll_raw_agg --
+5 5
+
+-- !two_hll_raw_agg_group --
+1 3 3
+2 3 3
+
+-- !two_hll_union_agg --
+5 5
+
+-- !two_hll_union_agg_group --
+1 3 3
+2 3 3
+
+-- !two_kurt --
+-1.3 -1.3
+
+-- !two_kurt_group --
+1 -1.5 -1.5
+2 -1.499999999999995 -1.499999999999998
+
+-- !two_map_agg --
+[1, 2, 3, 4, 5] ["a", "b", "c", "d", "e"] [10, 20, 30, 40, 50]
["a", "b", "c", "d", "e"]
+
+-- !two_map_agg_group --
+1 [1, 2, 3] ["a", "b", "c"] [10, 20, 30] ["a", "b", "c"]
+2 [1, 4, 5] ["a", "d", "e"] [10, 40, 50] ["a", "d", "e"]
+
+-- !two_max_by --
+e e
+
+-- !two_max_by_group --
+1 c c
+2 e e
+
+-- !two_min_by --
+a a
+
+-- !two_min_by_group --
+1 a a
+2 a a
+
+-- !two_percentile --
+3.0 30.0
+
+-- !two_percentile_group --
+1 2.0 20.0
+2 4.0 40.0
+
+-- !two_percentile_approx --
+3.0 30.0
+
+-- !two_percentile_approx_group --
+1 2.0 20.0
+2 4.0 40.0
+
+-- !two_percentile_array --
+[2, 3, 4] [20, 30, 40]
+
+-- !two_percentile_array_group --
+1 [1.5, 2, 2.5] [15, 20, 25]
+2 [2.5, 4, 4.5] [25, 40, 45]
+
+-- !two_percentile_approx_weighted --
+3.857142925262451 38.57143020629883
+
+-- !two_percentile_approx_weighted_group --
+1 2.400000095367432 24.0
+2 4.44444465637207 44.44444274902344
+
+-- !two_topn --
+{"e":1,"d":1,"c":1} {"5":1,"4":1,"3":1}
+
+-- !two_topn_group --
+1 {"c":1,"b":1,"a":1} {"3":1,"2":1,"1":1}
+2 {"e":1,"d":1,"a":1} {"5":1,"4":1,"1":1}
+
+-- !two_topn_array --
+["e", "d", "c"] ["5", "4", "3"]
+
+-- !two_topn_array_group --
+1 ["c", "b", "a"] ["3", "2", "1"]
+2 ["e", "d", "a"] ["5", "4", "1"]
+
+-- !two_topn_weighted --
+["e", "d", "c"] ["5", "4", "3"]
+
+-- !two_topn_weighted_group --
+1 ["c", "b", "a"] ["3", "2", "1"]
+2 ["e", "d", "a"] ["5", "4", "1"]
+
+-- !percentile_res --
+2.0 40.0
+
+-- !percentile_res_group --
+1.5 25.0
+2.5 45.0
+
+-- !ema --
+2.501954556443252 0.8055193463643526
+
+-- !ema_group --
+1.500977039337158 0.4611636182575578
+2.501953125000455 0.7772022820853798
+
diff --git
a/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.out
b/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.out
index 18088719ce3..d051d2efe37 100644
---
a/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.out
+++
b/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.out
@@ -38,3 +38,12 @@ PhysicalResultSink
--------hashAgg[LOCAL]
----------PhysicalOlapScan[t1000_2]
+-- !agg_phase3 --
+PhysicalResultSink
+--PhysicalDistribute[DistributionSpecGather]
+----hashAgg[DISTINCT_GLOBAL]
+------hashAgg[GLOBAL]
+--------PhysicalDistribute[DistributionSpecHash]
+----------hashAgg[LOCAL]
+------------PhysicalTVFRelation
+
diff --git
a/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.out
b/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.out
index 05ef347e89b..09ac8a07824 100644
---
a/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.out
+++
b/regression-test/data/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.out
@@ -110,3 +110,18 @@ PhysicalResultSink
--------hashAgg[LOCAL]
----------PhysicalOlapScan[t1000]
+-- !count_distinct_group --
+5 5
+
+-- !count_distinct_group_with_gby --
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+1 1
+
diff --git
a/regression-test/data/nereids_rules_p0/expression/test_convert_median_to_percentile.out
b/regression-test/data/nereids_rules_p0/expression/test_convert_median_to_percentile.out
index 3cccc3d6fb0..43e5deec56b 100644
---
a/regression-test/data/nereids_rules_p0/expression/test_convert_median_to_percentile.out
+++
b/regression-test/data/nereids_rules_p0/expression/test_convert_median_to_percentile.out
@@ -19,3 +19,6 @@
-- !select_6 --
2001 125.5
+-- !median_distinct --
+5.5 1
+
diff --git
a/regression-test/suites/nereids_function_p0/agg_function/agg_distinct_function.groovy
b/regression-test/suites/nereids_function_p0/agg_function/agg_distinct_function.groovy
new file mode 100644
index 00000000000..bd555aa6fac
--- /dev/null
+++
b/regression-test/suites/nereids_function_p0/agg_function/agg_distinct_function.groovy
@@ -0,0 +1,212 @@
+// 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.
+
+suite("agg_distinct_function") {
+ sql "drop table if exists agg_distinct_function"
+ sql """
+ create table agg_distinct_function (
+ k int,
+ a int,
+ b int,
+ s varchar(10),
+ w int
+ ) engine=olap
+ duplicate key(k)
+ distributed by hash(k) buckets 1
+ properties ("replication_num" = "1")
+ """
+
+ // The duplicate rows make DISTINCT observable. Every query is run both as
a
+ // scalar aggregation and as a grouped aggregation.
+ sql """
+ insert into agg_distinct_function values
+ (1, 1, 10, 'a', 1), (1, 1, 10, 'a', 1),
+ (1, 2, 20, 'b', 2), (1, 3, 30, 'c', 3),
+ (2, 1, 10, 'a', 1), (2, 4, 40, 'd', 4),
+ (2, 4, 40, 'd', 4), (2, 5, 50, 'e', 5)
+ """
+
+ qt_array_agg "select array_sort(array_agg(distinct a)) from
agg_distinct_function"
+ order_qt_array_agg_group "select k, array_sort(array_agg(distinct a)) from
agg_distinct_function group by k order by k"
+ qt_avg "select avg(distinct a) from agg_distinct_function"
+ order_qt_avg_group "select k, avg(distinct a) from agg_distinct_function
group by k order by k"
+ qt_avg_weighted "select avg_weighted(distinct a, w) from
agg_distinct_function"
+ order_qt_avg_weighted_group "select k, avg_weighted(distinct a, w) from
agg_distinct_function group by k order by k"
+ qt_collect_list "select array_sort(collect_list(distinct a)) from
agg_distinct_function"
+ order_qt_collect_list_group "select k, array_sort(collect_list(distinct
a)) from agg_distinct_function group by k order by k"
+ qt_collect_set "select array_sort(collect_set(distinct a)) from
agg_distinct_function"
+ order_qt_collect_set_group "select k, array_sort(collect_set(distinct a))
from agg_distinct_function group by k order by k"
+ qt_corr_welford "select corr_welford(distinct a, b) from
agg_distinct_function"
+ order_qt_corr_welford_group "select k, corr_welford(distinct a, b) from
agg_distinct_function group by k order by k"
+ qt_corr "select corr(distinct a, b) from agg_distinct_function"
+ order_qt_corr_group "select k, corr(distinct a, b) from
agg_distinct_function group by k order by k"
+ qt_covar "select covar(distinct a, b) from agg_distinct_function"
+ order_qt_covar_group "select k, covar(distinct a, b) from
agg_distinct_function group by k order by k"
+ qt_covar_samp "select covar_samp(distinct a, b) from agg_distinct_function"
+ order_qt_covar_samp_group "select k, covar_samp(distinct a, b) from
agg_distinct_function group by k order by k"
+ qt_group_bit_and "select group_bit_and(distinct a) from
agg_distinct_function"
+ order_qt_group_bit_and_group "select k, group_bit_and(distinct a) from
agg_distinct_function group by k order by k"
+ qt_group_bit_or "select group_bit_or(distinct a) from
agg_distinct_function"
+ order_qt_group_bit_or_group "select k, group_bit_or(distinct a) from
agg_distinct_function group by k order by k"
+ qt_group_bit_xor "select group_bit_xor(distinct a) from
agg_distinct_function"
+ order_qt_group_bit_xor_group "select k, group_bit_xor(distinct a) from
agg_distinct_function group by k order by k"
+// qt_group_bitmap_xor "select bitmap_to_string(group_bitmap_xor(distinct
bitmap_hash(a))) from agg_distinct_function"
+// order_qt_group_bitmap_xor_group "select k,
bitmap_to_string(group_bitmap_xor(distinct bitmap_hash(a))) from
agg_distinct_function group by k order by k"
+ qt_group_concat "select group_concat(distinct s order by s) from
agg_distinct_function"
+ order_qt_group_concat_group "select k, group_concat(distinct s order by s)
from agg_distinct_function group by k order by k"
+ qt_histogram "select histogram(distinct a) from agg_distinct_function"
+ order_qt_histogram_group "select k, histogram(distinct a) from
agg_distinct_function group by k order by k"
+ qt_hll_raw_agg "select hll_cardinality(hll_raw_agg(distinct hll_hash(a)))
from agg_distinct_function"
+ order_qt_hll_raw_agg_group "select k, hll_cardinality(hll_raw_agg(distinct
hll_hash(a))) from agg_distinct_function group by k order by k"
+ qt_hll_union_agg "select hll_union_agg(distinct hll_hash(a)) from
agg_distinct_function"
+ order_qt_hll_union_agg_group "select k, hll_union_agg(distinct
hll_hash(a)) from agg_distinct_function group by k order by k"
+ qt_kurt "select kurt(distinct a) from agg_distinct_function"
+ order_qt_kurt_group "select k, kurt(distinct a) from agg_distinct_function
group by k order by k"
+ order_qt_map_agg_group """
+ SELECT
+ array_sort(map_keys(m)) AS sorted_keys,
+ array_sortby(map_values(m), map_keys(m)) AS values_by_sorted_key
+ FROM (
+ SELECT map_agg(DISTINCT a, s) AS m
+ FROM agg_distinct_function
+ group by k
+ ) t;
+ """
+ order_qt_map_agg """
+ SELECT
+ array_sort(map_keys(m)) AS sorted_keys,
+ array_sortby(map_values(m), map_keys(m)) AS values_by_sorted_key
+ FROM (
+ SELECT map_agg(DISTINCT a, s) AS m
+ FROM agg_distinct_function
+ ) t;
+ """
+ qt_max_by "select max_by(distinct s, a) from agg_distinct_function"
+ order_qt_max_by_group "select k, max_by(distinct s, a) from
agg_distinct_function group by k order by k"
+ qt_min_by "select min_by(distinct s, a) from agg_distinct_function"
+ order_qt_min_by_group "select k, min_by(distinct s, a) from
agg_distinct_function group by k order by k"
+ qt_percentile "select percentile(distinct a, 0.5) from
agg_distinct_function"
+ order_qt_percentile_group "select k, percentile(distinct a, 0.5) from
agg_distinct_function group by k order by k"
+ qt_percentile_approx "select percentile_approx(distinct a, 0.5) from
agg_distinct_function"
+ order_qt_percentile_approx_group "select k, percentile_approx(distinct a,
0.5) from agg_distinct_function group by k order by k"
+ qt_percentile_array "select percentile_array(distinct a, [0.25, 0.5,
0.75]) from agg_distinct_function"
+ order_qt_percentile_array_group "select k, percentile_array(distinct a,
[0.25, 0.5, 0.75]) from agg_distinct_function group by k order by k"
+ qt_percentile_approx_weighted "select percentile_approx_weighted(distinct
a, w, 0.5) from agg_distinct_function"
+ order_qt_percentile_approx_weighted_group "select k,
percentile_approx_weighted(distinct a, w, 0.5) from agg_distinct_function group
by k order by k"
+ qt_topn "select topn(distinct s, 3) from agg_distinct_function"
+ order_qt_topn_group "select k, topn(distinct s, 3) from
agg_distinct_function group by k order by k"
+ qt_topn_array "select topn_array(distinct s, 3) from agg_distinct_function"
+ order_qt_topn_array_group "select k, topn_array(distinct s, 3) from
agg_distinct_function group by k order by k"
+ qt_topn_weighted "select topn_weighted(distinct s, w, 3) from
agg_distinct_function"
+ order_qt_topn_weighted_group "select k, topn_weighted(distinct s, w, 3)
from agg_distinct_function group by k order by k"
+ sql "select count_by_enum(distinct s) from agg_distinct_function"
+ sql "select k, count_by_enum(distinct s) from agg_distinct_function group
by k order by k"
+
+ // Each pair uses different DISTINCT argument groups and exercises the CTE
split path.
+ qt_two_distinct_functions "select array_sort(array_agg(distinct a)),
array_sort(array_agg(distinct b)) from agg_distinct_function"
+ order_qt_two_distinct_functions_group "select k,
array_sort(array_agg(distinct a)), array_sort(array_agg(distinct b)) from
agg_distinct_function group by k order by k"
+ qt_two_avg "select avg(distinct a), avg(distinct b) from
agg_distinct_function"
+ order_qt_two_avg_group "select k, avg(distinct a), avg(distinct b) from
agg_distinct_function group by k order by k"
+ qt_two_avg_weighted "select avg_weighted(distinct a, w),
avg_weighted(distinct b, w) from agg_distinct_function"
+ order_qt_two_avg_weighted_group "select k, avg_weighted(distinct a, w),
avg_weighted(distinct b, w) from agg_distinct_function group by k order by k"
+ qt_two_collect_list "select array_sort(collect_list(distinct a)),
array_sort(collect_list(distinct b)) from agg_distinct_function"
+ order_qt_two_collect_list_group "select k,
array_sort(collect_list(distinct a)), array_sort(collect_list(distinct b)) from
agg_distinct_function group by k order by k"
+ qt_two_collect_set "select array_sort(collect_set(distinct a)),
array_sort(collect_set(distinct b)) from agg_distinct_function"
+ order_qt_two_collect_set_group "select k, array_sort(collect_set(distinct
a)), array_sort(collect_set(distinct b)) from agg_distinct_function group by k
order by k"
+ qt_two_corr_welford "select corr_welford(distinct a, b),
corr_welford(distinct a, w) from agg_distinct_function"
+ order_qt_two_corr_welford_group "select k, corr_welford(distinct a, b),
corr_welford(distinct a, w) from agg_distinct_function group by k order by k"
+ qt_two_corr "select corr(distinct a, b), corr(distinct a, w) from
agg_distinct_function"
+ order_qt_two_corr_group "select k, corr(distinct a, b), corr(distinct a,
w) from agg_distinct_function group by k order by k"
+ qt_two_covar "select covar(distinct a, b), covar(distinct a, w) from
agg_distinct_function"
+ order_qt_two_covar_group "select k, covar(distinct a, b), covar(distinct
a, w) from agg_distinct_function group by k order by k"
+ qt_two_covar_samp "select covar_samp(distinct a, b), covar_samp(distinct
a, w) from agg_distinct_function"
+ order_qt_two_covar_samp_group "select k, covar_samp(distinct a, b),
covar_samp(distinct a, w) from agg_distinct_function group by k order by k"
+ qt_two_group_bit_and "select group_bit_and(distinct a),
group_bit_and(distinct b) from agg_distinct_function"
+ order_qt_two_group_bit_and_group "select k, group_bit_and(distinct a),
group_bit_and(distinct b) from agg_distinct_function group by k order by k"
+ qt_two_group_bit_or "select group_bit_or(distinct a),
group_bit_or(distinct b) from agg_distinct_function"
+ order_qt_two_group_bit_or_group "select k, group_bit_or(distinct a),
group_bit_or(distinct b) from agg_distinct_function group by k order by k"
+ qt_two_group_bit_xor "select group_bit_xor(distinct a),
group_bit_xor(distinct b) from agg_distinct_function"
+ order_qt_two_group_bit_xor_group "select k, group_bit_xor(distinct a),
group_bit_xor(distinct b) from agg_distinct_function group by k order by k"
+// qt_two_group_bitmap_xor "select
bitmap_to_string(group_bitmap_xor(distinct bitmap_hash(a))),
bitmap_to_string(group_bitmap_xor(distinct bitmap_hash(b))) from
agg_distinct_function"
+// order_qt_two_group_bitmap_xor_group "select k,
bitmap_to_string(group_bitmap_xor(distinct bitmap_hash(a))),
bitmap_to_string(group_bitmap_xor(distinct bitmap_hash(b))) from
agg_distinct_function group by k order by k"
+ qt_two_group_concat "select group_concat(distinct s order by s),
group_concat(distinct cast(a as string) order by cast(a as string)) from
agg_distinct_function"
+ order_qt_two_group_concat_group "select k, group_concat(distinct s order
by s), group_concat(distinct cast(a as string) order by cast(a as string)) from
agg_distinct_function group by k order by k"
+ qt_two_histogram "select histogram(distinct a), histogram(distinct b) from
agg_distinct_function"
+ order_qt_two_histogram_group "select k, histogram(distinct a),
histogram(distinct b) from agg_distinct_function group by k order by k"
+ qt_two_hll_raw_agg "select hll_cardinality(hll_raw_agg(distinct
hll_hash(a))), hll_cardinality(hll_raw_agg(distinct hll_hash(b))) from
agg_distinct_function"
+ order_qt_two_hll_raw_agg_group "select k,
hll_cardinality(hll_raw_agg(distinct hll_hash(a))),
hll_cardinality(hll_raw_agg(distinct hll_hash(b))) from agg_distinct_function
group by k order by k"
+ qt_two_hll_union_agg "select hll_union_agg(distinct hll_hash(a)),
hll_union_agg(distinct hll_hash(b)) from agg_distinct_function"
+ order_qt_two_hll_union_agg_group "select k, hll_union_agg(distinct
hll_hash(a)), hll_union_agg(distinct hll_hash(b)) from agg_distinct_function
group by k order by k"
+ qt_two_kurt "select kurt(distinct a), kurt(distinct b) from
agg_distinct_function"
+ order_qt_two_kurt_group "select k, kurt(distinct a), kurt(distinct b) from
agg_distinct_function group by k order by k"
+ qt_two_map_agg """
+ select array_sort(map_keys(a_map)), array_sortby(map_values(a_map),
map_keys(a_map)),
+ array_sort(map_keys(b_map)), array_sortby(map_values(b_map),
map_keys(b_map))
+ from (
+ select map_agg(distinct a, s) as a_map, map_agg(distinct b, s) as
b_map
+ from agg_distinct_function
+ ) t
+ """
+ order_qt_two_map_agg_group """
+ select k, array_sort(map_keys(a_map)), array_sortby(map_values(a_map),
map_keys(a_map)),
+ array_sort(map_keys(b_map)), array_sortby(map_values(b_map),
map_keys(b_map))
+ from (
+ select k, map_agg(distinct a, s) as a_map, map_agg(distinct b, s)
as b_map
+ from agg_distinct_function
+ group by k
+ ) t
+ order by k
+ """
+ qt_two_max_by "select max_by(distinct s, a), max_by(distinct s, b) from
agg_distinct_function"
+ order_qt_two_max_by_group "select k, max_by(distinct s, a),
max_by(distinct s, b) from agg_distinct_function group by k order by k"
+ qt_two_min_by "select min_by(distinct s, a), min_by(distinct s, b) from
agg_distinct_function"
+ order_qt_two_min_by_group "select k, min_by(distinct s, a),
min_by(distinct s, b) from agg_distinct_function group by k order by k"
+ qt_two_percentile "select percentile(distinct a, 0.5), percentile(distinct
b, 0.5) from agg_distinct_function"
+ order_qt_two_percentile_group "select k, percentile(distinct a, 0.5),
percentile(distinct b, 0.5) from agg_distinct_function group by k order by k"
+ qt_two_percentile_approx "select percentile_approx(distinct a, 0.5),
percentile_approx(distinct b, 0.5) from agg_distinct_function"
+ order_qt_two_percentile_approx_group "select k, percentile_approx(distinct
a, 0.5), percentile_approx(distinct b, 0.5) from agg_distinct_function group by
k order by k"
+ qt_two_percentile_array "select percentile_array(distinct a, [0.25, 0.5,
0.75]), percentile_array(distinct b, [0.25, 0.5, 0.75]) from
agg_distinct_function"
+ order_qt_two_percentile_array_group "select k, percentile_array(distinct
a, [0.25, 0.5, 0.75]), percentile_array(distinct b, [0.25, 0.5, 0.75]) from
agg_distinct_function group by k order by k"
+ qt_two_percentile_approx_weighted "select
percentile_approx_weighted(distinct a, w, 0.5),
percentile_approx_weighted(distinct b, w, 0.5) from agg_distinct_function"
+ order_qt_two_percentile_approx_weighted_group "select k,
percentile_approx_weighted(distinct a, w, 0.5),
percentile_approx_weighted(distinct b, w, 0.5) from agg_distinct_function group
by k order by k"
+ qt_two_topn "select topn(distinct s, 3), topn(distinct cast(a as string),
3) from agg_distinct_function"
+ order_qt_two_topn_group "select k, topn(distinct s, 3), topn(distinct
cast(a as string), 3) from agg_distinct_function group by k order by k"
+ qt_two_topn_array "select topn_array(distinct s, 3), topn_array(distinct
cast(a as string), 3) from agg_distinct_function"
+ order_qt_two_topn_array_group "select k, topn_array(distinct s, 3),
topn_array(distinct cast(a as string), 3) from agg_distinct_function group by k
order by k"
+ qt_two_topn_weighted "select topn_weighted(distinct s, w, 3),
topn_weighted(distinct cast(a as string), w, 3) from agg_distinct_function"
+ order_qt_two_topn_weighted_group "select k, topn_weighted(distinct s, w,
3), topn_weighted(distinct cast(a as string), w, 3) from agg_distinct_function
group by k order by k"
+ sql "select count_by_enum(distinct s), count_by_enum(distinct cast(a as
string)) from agg_distinct_function"
+ sql "select k, count_by_enum(distinct s), count_by_enum(distinct cast(a as
string)) from agg_distinct_function group by k order by k"
+ order_qt_percentile_res """select percentile_reservoir(distinct a, 0.25),
percentile_reservoir(distinct b, 0.75) from agg_distinct_function"""
+ order_qt_percentile_res_group """select percentile_reservoir(distinct a,
0.25), percentile_reservoir(distinct b, 0.75) from agg_distinct_function group
by k"""
+ order_qt_ema """select exponential_moving_average(distinct 1.0, w,
b),exponential_moving_average(distinct 5.0, a, b) from agg_distinct_function"""
+ order_qt_ema_group """select exponential_moving_average(distinct 1.0, w,
b),exponential_moving_average(distinct 5.0, a, b) from agg_distinct_function
group by k"""
+
+ sql """
+ select percentile_reservoir(distinct a, 0.25),
percentile_reservoir(distinct a, 0.75)
+ from agg_distinct_function group by rollup(k)
+ """
+ sql """
+ select exponential_moving_average(distinct 1.0, a,
b),exponential_moving_average(distinct 5.0, a, b)
+ from agg_distinct_function group by rollup(k)
+ """
+
+ test {
+ sql "select bitmap_to_string(group_bitmap_xor(distinct
bitmap_hash(a))) from agg_distinct_function"
+ exception "group_bitmap_xor does not support DISTINCT"
+ }
+}
diff --git
a/regression-test/suites/nereids_p0/aggregate/agg_group_concat.groovy
b/regression-test/suites/nereids_p0/aggregate/agg_group_concat.groovy
index cdf5d5292fa..6fc8130b67f 100644
--- a/regression-test/suites/nereids_p0/aggregate/agg_group_concat.groovy
+++ b/regression-test/suites/nereids_p0/aggregate/agg_group_concat.groovy
@@ -133,4 +133,13 @@ suite("agg_group_concat") {
insert into test_distinct_multi
values(1,2,3,'abc','2024-01-02'),(1,2,4,'abc','2024-01-03'),(2,2,4,'abcd','2024-01-02'),(1,2,3,'abcd','2024-01-04'),(1,2,4,'eee','2024-02-02'),(2,2,4,'abc','2024-01-02');
"""
qt_test "select group_concat( distinct d order by d) from
test_distinct_multi order by 1; "
+
+ test {
+ sql "select multi_distinct_GROUP_CONCAT(a, c) from test_distinct_multi
group by b; "
+ exception "separator must be a constant"
+ }
+ test {
+ sql "select GROUP_CONCAT(a, c order by c) from test_distinct_multi
group by b; "
+ exception "separator must be a constant"
+ }
}
diff --git
a/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.groovy
b/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.groovy
index 953c233c0d5..10d3d8185ca 100644
---
a/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.groovy
+++
b/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_rewriter.groovy
@@ -33,4 +33,25 @@ suite("distinct_agg_rewriter") {
select count(distinct d_200) from t1000_2 group by b_5;"""
qt_use_multi_distinct """explain shape plan
select count(distinct d_200) from t1000_2 group by a_1;"""
-}
\ No newline at end of file
+
+ sql "set agg_phase=4"
+ sql "select group_concat(distinct dst_key1 order by dst_key2) from
t_gbykey_10_dstkey_10_1000_id group by gby_key"
+ test {
+ sql """select number % 2, count(distinct cast(number as varchar),
cast(number as varchar)),
+ group_concat(distinct cast(number as varchar) order by number + 1)
from numbers('number'='10') group by number % 2"""
+ exception "Unsupported query"
+ }
+
+ test {
+ sql """select count(distinct cast(number as varchar), cast(number as
varchar)),
+ group_concat(distinct cast(number as varchar) order by number + 1)
from numbers('number'='10')"""
+ exception "Unsupported query"
+ }
+
+ // expect to have 3 HashAgg instead of 4 HashAgg
+ sql "set agg_phase=3"
+ qt_agg_phase3 """explain shape plan
+ select number % 2, count(distinct number)
+ from numbers('number'='10')
+ group by number % 2;"""
+}
diff --git
a/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.groovy
b/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.groovy
index a565f55a0bf..23717e8491e 100644
---
a/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.groovy
+++
b/regression-test/suites/nereids_rules_p0/agg_strategy/distinct_agg_strategy_selector.groovy
@@ -52,4 +52,47 @@ suite("distinct_agg_strategy_selector") {
contains "multi_distinct_count"
}
sql "set multi_distinct_strategy=0 "
+
+ // test
+ order_qt_count_distinct_group "select count(distinct a_1,b_5),
count(distinct b_5,a_1) from t1000;"
+ order_qt_count_distinct_group_with_gby "select count(distinct a_1,b_5),
count(distinct b_5,a_1) from t1000 group by c_10;"
+
+ multi_sql """
+ SET enable_nereids_planner = true;
+
+ DROP VIEW IF EXISTS v_distinct_guard_repro;
+ DROP TABLE IF EXISTS t_distinct_guard_repro;
+
+ CREATE TABLE t_distinct_guard_repro (
+ id INT,
+ a DECIMAL(20, 2),
+ b INT
+ )
+ ENGINE = OLAP
+ DUPLICATE KEY(id)
+ DISTRIBUTED BY HASH(id) BUCKETS 1
+ PROPERTIES (
+ "replication_num" = "1"
+ );
+
+ INSERT INTO t_distinct_guard_repro VALUES
+ (1, 1.00, 10),
+ (2, 1.00, 10),
+ (3, 2.00, 20),
+ (4, 3.00, 30);
+ """
+ sql "SET enable_decimal256 = false;"
+
+ sql """CREATE VIEW v_distinct_guard_repro AS
+ SELECT
+ SUM(DISTINCT a) AS distinct_sum_a,
+ ARRAY_AGG(DISTINCT b) AS distinct_b_values
+ FROM t_distinct_guard_repro;"""
+
+ sql "SET enable_decimal256 = true;"
+
+ sql """SELECT
+ distinct_sum_a,
+ array_sort(distinct_b_values)
+ FROM v_distinct_guard_repro;"""
}
\ No newline at end of file
diff --git
a/regression-test/suites/nereids_rules_p0/expression/test_convert_median_to_percentile.groovy
b/regression-test/suites/nereids_rules_p0/expression/test_convert_median_to_percentile.groovy
index 2d8cf3a8b59..11c03bb37cd 100644
---
a/regression-test/suites/nereids_rules_p0/expression/test_convert_median_to_percentile.groovy
+++
b/regression-test/suites/nereids_rules_p0/expression/test_convert_median_to_percentile.groovy
@@ -73,6 +73,19 @@ suite("test_convert_median_to_percentile") {
qt_select_5 "${sql5}"
qt_select_6 "${sql6}"
+ sql "DROP TABLE IF EXISTS median_distinct"
+ sql """
+ CREATE TABLE median_distinct (
+ id INT,
+ value INT
+ )
+ DISTRIBUTED BY HASH(id) BUCKETS 1
+ PROPERTIES ("replication_num" = "1")
+ """
+ sql "INSERT INTO median_distinct VALUES (1, 1), (2, 1), (3, 10)"
+ order_qt_median_distinct "SELECT median(DISTINCT value), median(value)
FROM median_distinct"
+ sql "DROP TABLE IF EXISTS median_distinct"
+
sql "DROP TABLE if exists sales"
sql "DROP DATABASE if exists test_convert_median_to_percentile"
}
diff --git
a/regression-test/suites/query_p0/group_concat/test_group_concat.groovy
b/regression-test/suites/query_p0/group_concat/test_group_concat.groovy
index a60514c719f..eeb3cb0cff7 100644
--- a/regression-test/suites/query_p0/group_concat/test_group_concat.groovy
+++ b/regression-test/suites/query_p0/group_concat/test_group_concat.groovy
@@ -91,7 +91,7 @@ suite("test_group_concat", "query,p0,arrow_flight_sql") {
// test SPLIT_MULTI_DISTINCT could work right with can not be banned
aggregation
qt_select_13 """
select
- group_concat( distinct b1, cast(b2 as varchar)), group_concat(
distinct b3, '?')
+ group_concat( distinct b1, ','), group_concat( distinct b3,
'?')
from
table_group_concat
group by
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]