You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2022/12/26 16:38:10 UTC
[doris] branch master updated: [Feature](Nereids) Support hll and count for materialized index. (#15275)
This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 325d247b92 [Feature](Nereids) Support hll and count for materialized index. (#15275)
325d247b92 is described below
commit 325d247b9267de413d94018cbc7271c537270bcd
Author: Shuo Wang <wa...@gmail.com>
AuthorDate: Tue Dec 27 00:38:04 2022 +0800
[Feature](Nereids) Support hll and count for materialized index. (#15275)
---
.../doris/catalog/BuiltinAggregateFunctions.java | 4 +-
.../mv/SelectMaterializedIndexWithAggregate.java | 182 ++++++++++++++--
.../rewrite/logical/CountDistinctRewrite.java | 5 +-
.../trees/expressions/functions/agg/HllUnion.java | 6 +
.../expressions/functions/agg/HllUnionAgg.java | 6 +
.../trees/expressions/functions/agg/Ndv.java | 121 +++++++++++
.../visitor/AggregateFunctionVisitor.java | 15 ++
.../org/apache/doris/nereids/types/DataType.java | 4 +
.../doris/nereids/rules/mv/SelectMvIndexTest.java | 242 ++++++++++-----------
9 files changed, 442 insertions(+), 143 deletions(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinAggregateFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinAggregateFunctions.java
index 37d518a4eb..863057988e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinAggregateFunctions.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinAggregateFunctions.java
@@ -31,6 +31,7 @@ import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnion;
import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnionAgg;
import org.apache.doris.nereids.trees.expressions.functions.agg.Max;
import org.apache.doris.nereids.trees.expressions.functions.agg.Min;
+import org.apache.doris.nereids.trees.expressions.functions.agg.Ndv;
import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
import com.google.common.collect.ImmutableList;
@@ -57,7 +58,8 @@ public class BuiltinAggregateFunctions implements FunctionHelper {
agg(Sum.class),
agg(GroupBitAnd.class, "group_bit_and"),
agg(GroupBitOr.class, "group_bit_or"),
- agg(GroupBitXor.class, "group_bit_xor")
+ agg(GroupBitXor.class, "group_bit_xor"),
+ agg(Ndv.class)
);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/mv/SelectMaterializedIndexWithAggregate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/mv/SelectMaterializedIndexWithAggregate.java
index f1ed0236b2..c189292510 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/mv/SelectMaterializedIndexWithAggregate.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/mv/SelectMaterializedIndexWithAggregate.java
@@ -35,9 +35,13 @@ import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
import org.apache.doris.nereids.trees.expressions.functions.agg.BitmapUnionCount;
import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnion;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnionAgg;
import org.apache.doris.nereids.trees.expressions.functions.agg.Max;
import org.apache.doris.nereids.trees.expressions.functions.agg.Min;
+import org.apache.doris.nereids.trees.expressions.functions.agg.Ndv;
import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.HllHash;
import org.apache.doris.nereids.trees.expressions.functions.scalar.ToBitmap;
import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
@@ -136,8 +140,8 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
result.exprRewriteMap),
agg.isNormalized(),
agg.getSourceRepeat(),
- // Not that no need to replace slots in the filter, because the slots to replace
- // are value columns, which shouldn't appear in filters.
+ // Note that no need to replace slots in the filter, because the slots to
+ // replace are value columns, which shouldn't appear in filters.
filter.withChildren(
scan.withMaterializedIndexSelected(result.preAggStatus, result.indexId))
);
@@ -311,15 +315,13 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
.collect(Collectors.groupingBy(index -> index.getId() == table.getBaseIndexId()));
// Duplicate-keys table could use base index and indexes that pre-aggregation status is on.
- Stream<MaterializedIndex> checkPreAggResult = Stream.concat(
+ Set<MaterializedIndex> candidatesWithoutRewriting = Stream.concat(
indexesGroupByIsBaseOrNot.get(true).stream(),
indexesGroupByIsBaseOrNot.getOrDefault(false, ImmutableList.of())
.stream()
.filter(index -> checkPreAggStatus(scan, index.getId(), predicates,
aggregateFunctions, groupingExprs).isOn())
- );
-
- Set<MaterializedIndex> candidatesWithoutRewriting = checkPreAggResult.collect(Collectors.toSet());
+ ).collect(ImmutableSet.toImmutableSet());
// try to rewrite bitmap, hll by materialized index columns.
List<AggRewriteResult> candidatesWithRewriting = indexesGroupByIsBaseOrNot.getOrDefault(false,
@@ -328,6 +330,11 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
.filter(index -> !candidatesWithoutRewriting.contains(index))
.map(index -> rewriteAgg(index, scan, requiredScanOutput, predicates, aggregateFunctions,
groupingExprs))
+ .filter(aggRewriteResult -> checkPreAggStatus(scan, aggRewriteResult.index.getId(),
+ predicates,
+ // check pre-agg status of aggregate function that couldn't rewrite.
+ aggFuncsDiff(aggregateFunctions, aggRewriteResult),
+ groupingExprs).isOn())
.filter(result -> result.success)
.collect(Collectors.toList());
@@ -354,6 +361,16 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
}
}
+ private List<AggregateFunction> aggFuncsDiff(List<AggregateFunction> aggregateFunctions,
+ AggRewriteResult aggRewriteResult) {
+ if (aggRewriteResult.success) {
+ return ImmutableList.copyOf(Sets.difference(ImmutableSet.copyOf(aggregateFunctions),
+ aggRewriteResult.exprRewriteMap.aggFuncMap.keySet()));
+ } else {
+ return aggregateFunctions;
+ }
+ }
+
private static class SelectResult {
public final PreAggStatus preAggStatus;
public final long indexId;
@@ -468,10 +485,8 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
return checkAggFunc(sum, AggregateType.SUM, extractSlotId(sum.child()), context, false);
}
- // TODO: select count(xxx) for duplicated-keys table.
@Override
public PreAggStatus visitCount(Count count, CheckContext context) {
- // Now count(distinct key_column) is only supported for aggregate-keys and unique-keys OLAP table.
if (count.isDistinct() && count.arity() == 1) {
Optional<ExprId> exprIdOpt = extractSlotId(count.child(0));
if (exprIdOpt.isPresent() && context.exprIdToKeyColumn.containsKey(exprIdOpt.get())) {
@@ -492,6 +507,16 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
}
}
+ @Override
+ public PreAggStatus visitHllUnionAgg(HllUnionAgg hllUnionAgg, CheckContext context) {
+ Optional<Slot> slotOpt = ExpressionUtils.extractSlotOrCastOnSlot(hllUnionAgg.child());
+ if (slotOpt.isPresent() && context.exprIdToValueColumn.containsKey(slotOpt.get().getExprId())) {
+ return PreAggStatus.on();
+ } else {
+ return PreAggStatus.off("invalid hll_union_agg: " + hllUnionAgg.toSql());
+ }
+ }
+
private PreAggStatus checkAggFunc(
AggregateFunction aggFunc,
AggregateType matchingAggType,
@@ -711,34 +736,62 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
/**
* count(distinct col) -> bitmap_union_count(mv_bitmap_union_col)
+ * count(col) -> sum(mv_count_col)
*/
@Override
public Expression visitCount(Count count, RewriteContext context) {
if (count.isDistinct() && count.arity() == 1) {
+ // count(distinct col) -> bitmap_union_count(mv_bitmap_union_col)
Optional<Slot> slotOpt = ExpressionUtils.extractSlotOrCastOnSlot(count.child(0));
// count distinct a value column.
if (slotOpt.isPresent() && !context.checkContext.exprIdToKeyColumn.containsKey(
slotOpt.get().getExprId())) {
- String bitmapUnionCountColumn = CreateMaterializedViewStmt
+ String bitmapUnionColumn = CreateMaterializedViewStmt
.mvColumnBuilder(AggregateType.BITMAP_UNION.name().toLowerCase(), slotOpt.get().getName());
- Column mvColumn = context.checkContext.scan.getTable().getVisibleColumn(bitmapUnionCountColumn);
- // has bitmap_union_count column
+ Column mvColumn = context.checkContext.scan.getTable().getVisibleColumn(bitmapUnionColumn);
+ // has bitmap_union column
if (mvColumn != null && context.checkContext.exprIdToValueColumn.containsValue(mvColumn)) {
- Slot bitmapUnionCountSlot = context.checkContext.scan.getNonUserVisibleOutput()
+ Slot bitmapUnionSlot = context.checkContext.scan.getNonUserVisibleOutput()
.stream()
- .filter(s -> s.getName().equals(bitmapUnionCountColumn))
+ .filter(s -> s.getName().equals(bitmapUnionColumn))
.findFirst()
.get();
- context.exprRewriteMap.slotMap.put(slotOpt.get(), bitmapUnionCountSlot);
- context.exprRewriteMap.projectExprMap.put(slotOpt.get(), bitmapUnionCountSlot);
- BitmapUnionCount bitmapUnionCount = new BitmapUnionCount(bitmapUnionCountSlot);
+ context.exprRewriteMap.slotMap.put(slotOpt.get(), bitmapUnionSlot);
+ context.exprRewriteMap.projectExprMap.put(slotOpt.get(), bitmapUnionSlot);
+ BitmapUnionCount bitmapUnionCount = new BitmapUnionCount(bitmapUnionSlot);
context.exprRewriteMap.aggFuncMap.put(count, bitmapUnionCount);
return bitmapUnionCount;
}
}
+ } else if (!count.isDistinct() && count.arity() == 1) {
+ // count(col) -> sum(mv_count_col)
+
+ Optional<Slot> slotOpt = ExpressionUtils.extractSlotOrCastOnSlot(count.child(0));
+ // count a value column.
+ if (slotOpt.isPresent() && !context.checkContext.exprIdToKeyColumn.containsKey(
+ slotOpt.get().getExprId())) {
+ String countColumn = CreateMaterializedViewStmt
+ .mvColumnBuilder("count", slotOpt.get().getName());
+
+ Column mvColumn = context.checkContext.scan.getTable().getVisibleColumn(countColumn);
+ // has bitmap_union_count column
+ if (mvColumn != null && context.checkContext.exprIdToValueColumn.containsValue(mvColumn)) {
+ Slot countSlot = context.checkContext.scan.getNonUserVisibleOutput()
+ .stream()
+ .filter(s -> s.getName().equals(countColumn))
+ .findFirst()
+ .get();
+
+ context.exprRewriteMap.slotMap.put(slotOpt.get(), countSlot);
+ context.exprRewriteMap.projectExprMap.put(slotOpt.get(), countSlot);
+ Sum sum = new Sum(countSlot);
+ context.exprRewriteMap.aggFuncMap.put(count, sum);
+ return sum;
+ }
+ }
}
return count;
}
@@ -776,6 +829,103 @@ public class SelectMaterializedIndexWithAggregate extends AbstractSelectMaterial
return bitmapUnionCount;
}
+
+ /**
+ * hll_union(hll_hash(col)) to hll_union(mv_hll_union_col)
+ */
+ @Override
+ public Expression visitHllUnion(HllUnion hllUnion, RewriteContext context) {
+ if (hllUnion.child() instanceof HllHash) {
+ HllHash hllHash = (HllHash) hllUnion.child();
+ Optional<Slot> slotOpt = ExpressionUtils.extractSlotOrCastOnSlot(hllHash.child());
+ if (slotOpt.isPresent()) {
+ String hllUnionColumn = CreateMaterializedViewStmt
+ .mvColumnBuilder(AggregateType.HLL_UNION.name().toLowerCase(), slotOpt.get().getName());
+
+ Column mvColumn = context.checkContext.scan.getTable().getVisibleColumn(hllUnionColumn);
+ // has hll_union column
+ if (mvColumn != null && context.checkContext.exprIdToValueColumn.containsValue(mvColumn)) {
+ Slot hllUnionSlot = context.checkContext.scan.getNonUserVisibleOutput()
+ .stream()
+ .filter(s -> s.getName().equals(hllUnionColumn))
+ .findFirst()
+ .get();
+
+ context.exprRewriteMap.slotMap.put(slotOpt.get(), hllUnionSlot);
+ context.exprRewriteMap.projectExprMap.put(hllHash, hllUnionSlot);
+ HllUnion newHllUnion = new HllUnion(hllUnionSlot);
+ context.exprRewriteMap.aggFuncMap.put(hllUnion, newHllUnion);
+ return newHllUnion;
+ }
+ }
+ }
+
+ return hllUnion;
+ }
+
+ /**
+ * hll_union_agg(hll_hash(col)) -> hll_union-agg(mv_hll_union_col)
+ */
+ @Override
+ public Expression visitHllUnionAgg(HllUnionAgg hllUnionAgg, RewriteContext context) {
+ if (hllUnionAgg.child() instanceof HllHash) {
+ HllHash hllHash = (HllHash) hllUnionAgg.child();
+ Optional<Slot> slotOpt = ExpressionUtils.extractSlotOrCastOnSlot(hllHash.child());
+ if (slotOpt.isPresent()) {
+ String hllUnionColumn = CreateMaterializedViewStmt
+ .mvColumnBuilder(AggregateType.HLL_UNION.name().toLowerCase(), slotOpt.get().getName());
+
+ Column mvColumn = context.checkContext.scan.getTable().getVisibleColumn(hllUnionColumn);
+ // has hll_union column
+ if (mvColumn != null && context.checkContext.exprIdToValueColumn.containsValue(mvColumn)) {
+ Slot hllUnionSlot = context.checkContext.scan.getNonUserVisibleOutput()
+ .stream()
+ .filter(s -> s.getName().equals(hllUnionColumn))
+ .findFirst()
+ .get();
+
+ context.exprRewriteMap.slotMap.put(slotOpt.get(), hllUnionSlot);
+ context.exprRewriteMap.projectExprMap.put(hllHash, hllUnionSlot);
+ HllUnionAgg newHllUnionAgg = new HllUnionAgg(hllUnionSlot);
+ context.exprRewriteMap.aggFuncMap.put(hllUnionAgg, newHllUnionAgg);
+ return newHllUnionAgg;
+ }
+ }
+ }
+
+ return hllUnionAgg;
+ }
+
+ /**
+ * ndv(col) -> hll_union_agg(mv_hll_union_col)
+ */
+ @Override
+ public Expression visitNdv(Ndv ndv, RewriteContext context) {
+ Optional<Slot> slotOpt = ExpressionUtils.extractSlotOrCastOnSlot(ndv.child(0));
+ // ndv on a value column.
+ if (slotOpt.isPresent() && !context.checkContext.exprIdToKeyColumn.containsKey(
+ slotOpt.get().getExprId())) {
+ String hllUnionColumn = CreateMaterializedViewStmt
+ .mvColumnBuilder(AggregateType.HLL_UNION.name().toLowerCase(), slotOpt.get().getName());
+
+ Column mvColumn = context.checkContext.scan.getTable().getVisibleColumn(hllUnionColumn);
+ // has hll_union column
+ if (mvColumn != null && context.checkContext.exprIdToValueColumn.containsValue(mvColumn)) {
+ Slot hllUnionSlot = context.checkContext.scan.getNonUserVisibleOutput()
+ .stream()
+ .filter(s -> s.getName().equals(hllUnionColumn))
+ .findFirst()
+ .get();
+
+ context.exprRewriteMap.slotMap.put(slotOpt.get(), hllUnionSlot);
+ context.exprRewriteMap.projectExprMap.put(slotOpt.get(), hllUnionSlot);
+ HllUnionAgg hllUnionAgg = new HllUnionAgg(hllUnionSlot);
+ context.exprRewriteMap.aggFuncMap.put(ndv, hllUnionAgg);
+ return hllUnionAgg;
+ }
+ }
+ return ndv;
+ }
}
private List<NamedExpression> replaceAggOutput(
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/CountDistinctRewrite.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/CountDistinctRewrite.java
index 652783f5d4..8f7a070464 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/CountDistinctRewrite.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/CountDistinctRewrite.java
@@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.functions.agg.BitmapUnionCount;
import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnionAgg;
import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter;
import com.google.common.collect.ImmutableList;
@@ -34,7 +35,6 @@ import java.util.List;
* Rewrite count distinct for bitmap and hll type value.
* <p>
* count(distinct bitmap_col) -> bitmap_union_count(bitmap col)
- * todo: add support for HLL type.
*/
public class CountDistinctRewrite extends OneRewriteRuleFactory {
@Override
@@ -63,6 +63,9 @@ public class CountDistinctRewrite extends OneRewriteRuleFactory {
if (child.getDataType().isBitmap()) {
return new BitmapUnionCount(child);
}
+ if (child.getDataType().isHll()) {
+ return new HllUnionAgg(child);
+ }
}
return count;
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
index 415d4f9e55..b4fbddda94 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnion.java
@@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.HllType;
@@ -61,4 +62,9 @@ public class HllUnion extends AggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+ return visitor.visitHllUnion(this, context);
+ }
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
index 16c8519c3e..6b4f796beb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/HllUnionAgg.java
@@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DataType;
import org.apache.doris.nereids.types.HllType;
@@ -62,4 +63,9 @@ public class HllUnionAgg extends AggregateFunction
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+ return visitor.visitHllUnionAgg(this, context);
+ }
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java
new file mode 100644
index 0000000000..f38c75d22f
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/agg/Ndv.java
@@ -0,0 +1,121 @@
+// 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.trees.expressions.functions.agg;
+
+import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable;
+import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.BigIntType;
+import org.apache.doris.nereids.types.BitmapType;
+import org.apache.doris.nereids.types.BooleanType;
+import org.apache.doris.nereids.types.CharType;
+import org.apache.doris.nereids.types.DateTimeType;
+import org.apache.doris.nereids.types.DateTimeV2Type;
+import org.apache.doris.nereids.types.DateType;
+import org.apache.doris.nereids.types.DateV2Type;
+import org.apache.doris.nereids.types.DecimalV2Type;
+import org.apache.doris.nereids.types.DecimalV3Type;
+import org.apache.doris.nereids.types.DoubleType;
+import org.apache.doris.nereids.types.FloatType;
+import org.apache.doris.nereids.types.HllType;
+import org.apache.doris.nereids.types.IntegerType;
+import org.apache.doris.nereids.types.JsonType;
+import org.apache.doris.nereids.types.LargeIntType;
+import org.apache.doris.nereids.types.NullType;
+import org.apache.doris.nereids.types.QuantileStateType;
+import org.apache.doris.nereids.types.SmallIntType;
+import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.types.TimeType;
+import org.apache.doris.nereids.types.TimeV2Type;
+import org.apache.doris.nereids.types.TinyIntType;
+import org.apache.doris.nereids.types.VarcharType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * AggregateFunction 'ndv'. This class is generated by GenerateFunction.
+ */
+public class Ndv extends AggregateFunction
+ implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNotNullable {
+
+ public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+ FunctionSignature.ret(BigIntType.INSTANCE).args(TinyIntType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(SmallIntType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(IntegerType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(BigIntType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(LargeIntType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(FloatType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DoubleType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DecimalV2Type.SYSTEM_DEFAULT),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DecimalV3Type.DEFAULT_DECIMAL32),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DecimalV3Type.DEFAULT_DECIMAL64),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DecimalV3Type.DEFAULT_DECIMAL128),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(BooleanType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(StringType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DateType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DateV2Type.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(DateTimeV2Type.SYSTEM_DEFAULT),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(TimeType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(TimeV2Type.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(JsonType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(HllType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(BitmapType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(QuantileStateType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(NullType.INSTANCE),
+ FunctionSignature.ret(BigIntType.INSTANCE).args(CharType.SYSTEM_DEFAULT)
+ );
+
+ /**
+ * constructor with 1 argument.
+ */
+ public Ndv(Expression arg) {
+ super("ndv", arg);
+ }
+
+ /**
+ * withChildren.
+ */
+ @Override
+ public Ndv withChildren(List<Expression> children) {
+ Preconditions.checkArgument(children.size() == 1);
+ return new Ndv(children.get(0));
+ }
+
+ @Override
+ public List<FunctionSignature> getSignatures() {
+ return SIGNATURES;
+ }
+
+ @Override
+ public AggregateFunction withDistinctAndChildren(boolean isDistinct, List<Expression> children) {
+ return withChildren(children);
+ }
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+ return visitor.visitNdv(this, context);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/AggregateFunctionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/AggregateFunctionVisitor.java
index 77254fd830..b31f6d1811 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/AggregateFunctionVisitor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/AggregateFunctionVisitor.java
@@ -24,10 +24,13 @@ import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
import org.apache.doris.nereids.trees.expressions.functions.agg.GroupBitAnd;
import org.apache.doris.nereids.trees.expressions.functions.agg.GroupBitOr;
import org.apache.doris.nereids.trees.expressions.functions.agg.GroupBitXor;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnion;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnionAgg;
import org.apache.doris.nereids.trees.expressions.functions.agg.Max;
import org.apache.doris.nereids.trees.expressions.functions.agg.Min;
import org.apache.doris.nereids.trees.expressions.functions.agg.MultiDistinctCount;
import org.apache.doris.nereids.trees.expressions.functions.agg.MultiDistinctSum;
+import org.apache.doris.nereids.trees.expressions.functions.agg.Ndv;
import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
/** AggregateFunctionVisitor. */
@@ -77,4 +80,16 @@ public interface AggregateFunctionVisitor<R, C> {
default R visitBitmapUnionCount(BitmapUnionCount bitmapUnionCount, C context) {
return visitAggregateFunction(bitmapUnionCount, context);
}
+
+ default R visitNdv(Ndv ndv, C context) {
+ return visitAggregateFunction(ndv, context);
+ }
+
+ default R visitHllUnionAgg(HllUnionAgg hllUnionAgg, C context) {
+ return visitAggregateFunction(hllUnionAgg, context);
+ }
+
+ default R visitHllUnion(HllUnion hllUnion, C context) {
+ return visitAggregateFunction(hllUnion, context);
+ }
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
index 43486b528b..6abe61d9f7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java
@@ -488,6 +488,10 @@ public abstract class DataType implements AbstractDataType {
return this instanceof BitmapType;
}
+ public boolean isHll() {
+ return this instanceof HllType;
+ }
+
public DataType promotion() {
if (PROMOTION_MAP.containsKey(this.getClass())) {
return PROMOTION_MAP.get(this.getClass()).get();
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/mv/SelectMvIndexTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/mv/SelectMvIndexTest.java
index 0c5042b936..422041e93c 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/mv/SelectMvIndexTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/mv/SelectMvIndexTest.java
@@ -19,9 +19,16 @@ package org.apache.doris.nereids.rules.mv;
import org.apache.doris.catalog.FunctionSet;
import org.apache.doris.common.FeConstants;
+import org.apache.doris.nereids.trees.expressions.Alias;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction;
import org.apache.doris.nereids.trees.expressions.functions.agg.BitmapUnionCount;
import org.apache.doris.nereids.trees.expressions.functions.agg.Count;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnion;
+import org.apache.doris.nereids.trees.expressions.functions.agg.HllUnionAgg;
+import org.apache.doris.nereids.trees.expressions.functions.agg.Sum;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
import org.apache.doris.nereids.util.PatternMatchSupported;
@@ -135,17 +142,14 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
// dorisAssert.query(query2).explainWithout(QUERY_USE_EMPS_MV);
// }
- /**
- * TODO: enable this when union is supported.
- */
- @Disabled
+ @Test
public void testUnionQueryOnProjectionMV() throws Exception {
String createMVSql = "create materialized view " + EMPS_MV_NAME + " as select deptno, empid from "
+ EMPS_TABLE_NAME + " order by deptno;";
String union = "select empid from " + EMPS_TABLE_NAME + " where deptno > 300" + " union all select empid from"
+ " " + EMPS_TABLE_NAME + " where deptno < 200";
createMv(createMVSql);
- testMv(union, EMPS_MV_NAME);
+ testMvWithTwoTable(union, EMPS_MV_NAME, EMPS_MV_NAME);
}
@Test
@@ -167,22 +171,6 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
testMv(query, EMPS_MV_NAME);
}
- /*
- TODO
- The deduplicate materialized view is not yet supported
- @Test
- public void testAggQueryOnDeduplicatedMV() throws Exception {
- String deduplicateSQL = "select deptno, empid, name, salary, commission from " + EMPS_TABLE_NAME + " group "
- + "by" + " deptno, empid, name, salary, commission";
- String createMVSql = "create materialized view " + EMPS_MV_NAME + " as " + deduplicateSQL + ";";
- String query1 = "select deptno, sum(salary) from (" + deduplicateSQL + ") A group by deptno;";
- createMv(createMVSql);
- testMv(query1, EMPS_MV_NAME);
- String query2 = "select deptno, empid from " + EMPS_TABLE_NAME + ";";
- dorisAssert.query(query2).explainWithout(QUERY_USE_EMPS_MV);
- }
- */
-
@Test
public void testAggQueryOnAggMV3() throws Exception {
String createMVSql = "create materialized view " + EMPS_MV_NAME + " as select deptno, commission, sum(salary)"
@@ -308,11 +296,7 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
testMv(query, EMPS_TABLE_NAME);
}
- /**
- * Aggregation query with set operand
- * TODO: enable this when union is supported.
- */
- @Disabled
+ @Test
public void testAggQueryWithSetOperandOnAggMV() throws Exception {
String createMVSql = "create materialized view " + EMPS_MV_NAME + " as select deptno, count(salary) "
+ "from " + EMPS_TABLE_NAME + " group by deptno;";
@@ -321,7 +305,7 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
+ "select deptno, count(salary) + count(1) from " + EMPS_TABLE_NAME
+ " group by deptno;";
createMv(createMVSql);
- testMv(query, EMPS_TABLE_NAME);
+ testMvWithTwoTable(query, EMPS_TABLE_NAME, EMPS_TABLE_NAME);
}
@Test
@@ -627,28 +611,24 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
testMv(query, EMPS_MV_NAME);
}
- /**
- * TODO: enable this when union is supported.
- */
- @Disabled
+ @Test
public void testUnionAll() throws Exception {
- // String createEmpsMVsql = "create materialized view " + EMPS_MV_NAME + " as select empid, deptno from "
- // + EMPS_TABLE_NAME + " order by empid, deptno;";
- // String query = "select empid, deptno from " + EMPS_TABLE_NAME + " where empid >1 union all select empid,"
- // + " deptno from " + EMPS_TABLE_NAME + " where empid <0;";
- // dorisAssert.withMaterializedView(createEmpsMVsql).query(query).explainContains(QUERY_USE_EMPS_MV, 2);
+ String createEmpsMVsql = "create materialized view " + EMPS_MV_NAME + " as select empid, deptno from "
+ + EMPS_TABLE_NAME + " order by empid, deptno;";
+ String query = "select empid, deptno from " + EMPS_TABLE_NAME + " where empid >1 union all select empid,"
+ + " deptno from " + EMPS_TABLE_NAME + " where empid <0;";
+ createMv(createEmpsMVsql);
+ testMvWithTwoTable(query, EMPS_MV_NAME, EMPS_MV_NAME);
}
- /**
- * TODO: enable this when union is supported.
- */
- @Disabled
+ @Test
public void testUnionDistinct() throws Exception {
- // String createEmpsMVsql = "create materialized view " + EMPS_MV_NAME + " as select empid, deptno from "
- // + EMPS_TABLE_NAME + " order by empid, deptno;";
- // String query = "select empid, deptno from " + EMPS_TABLE_NAME + " where empid >1 union select empid,"
- // + " deptno from " + EMPS_TABLE_NAME + " where empid <0;";
- // dorisAssert.withMaterializedView(createEmpsMVsql).query(query).explainContains(QUERY_USE_EMPS_MV, 2);
+ String createEmpsMVsql = "create materialized view " + EMPS_MV_NAME + " as select empid, deptno from "
+ + EMPS_TABLE_NAME + " order by empid, deptno;";
+ createMv(createEmpsMVsql);
+ String query = "select empid, deptno from " + EMPS_TABLE_NAME + " where empid >1 union select empid,"
+ + " deptno from " + EMPS_TABLE_NAME + " where empid <0;";
+ testMvWithTwoTable(query, EMPS_MV_NAME, EMPS_MV_NAME);
}
/**
@@ -668,6 +648,7 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
String query = "select k1, k2 from agg_table;";
// todo: `preagg` should be ture when rollup could be used.
singleTableTest(query, "only_keys", false);
+ dropTable("agg_table", true);
}
/**
@@ -855,18 +836,30 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
dropTable(TEST_TABLE_NAME, true);
}
- /**
- * TODO: enable this when hll is supported.
- */
- @Disabled
+ @Test
public void testAggTableCountDistinctInHllType() throws Exception {
- // String aggTable = "CREATE TABLE " + TEST_TABLE_NAME + " (k1 int, v1 hll " + FunctionSet.HLL_UNION
- // + ") Aggregate KEY (k1) "
- // + "DISTRIBUTED BY HASH(k1) BUCKETS 3 PROPERTIES ('replication_num' = '1');";
- // dorisAssert.withTable(aggTable);
- // String query = "select k1, count(distinct v1) from " + TEST_TABLE_NAME + " group by k1;";
- // dorisAssert.query(query).explainContains(TEST_TABLE_NAME, "hll_union_agg");
- // dorisAssert.dropTable(TEST_TABLE_NAME, true);
+ String aggTable = "CREATE TABLE " + TEST_TABLE_NAME + " (k1 int, v1 hll " + FunctionSet.HLL_UNION
+ + ") Aggregate KEY (k1) "
+ + "DISTRIBUTED BY HASH(k1) BUCKETS 3 PROPERTIES ('replication_num' = '1');";
+ createTable(aggTable);
+ String query = "select k1, count(distinct v1) from " + TEST_TABLE_NAME + " group by k1;";
+ PlanChecker.from(connectContext)
+ .analyze(query)
+ .rewrite()
+ .matches(logicalAggregate(logicalOlapScan()).when(agg -> {
+ // k1#0, hll_union_agg(v1#1) AS `count(distinct v1)`#2
+ List<NamedExpression> output = agg.getOutputExpressions();
+ Assertions.assertEquals(2, output.size());
+ NamedExpression output1 = output.get(1);
+ Assertions.assertTrue(output1 instanceof Alias);
+ Alias alias = (Alias) output1;
+ Expression aliasChild = alias.child();
+ Assertions.assertTrue(aliasChild instanceof HllUnionAgg);
+ HllUnionAgg hllUnionAgg = (HllUnionAgg) aliasChild;
+ Assertions.assertEquals("v1", ((Slot) hllUnionAgg.child()).getName());
+ return true;
+ }));
+ dropTable(TEST_TABLE_NAME, true);
}
/**
@@ -904,17 +897,14 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
testMv(query, USER_TAG_TABLE_NAME);
}
- /**
- * TODO: enable this when hll is supported.
- */
- @Disabled
+ @Test
public void testNDVToHll() throws Exception {
- // String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
- // + "`" + FunctionSet.HLL_UNION + "`(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME
- // + " group by user_id;";
- // dorisAssert.withMaterializedView(createUserTagMVSql);
- // String query = "select ndv(tag_id) from " + USER_TAG_TABLE_NAME + ";";
- // dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, "hll_union_agg");
+ String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
+ + "`" + FunctionSet.HLL_UNION + "`(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME
+ + " group by user_id;";
+ createMv(createUserTagMVSql);
+ String query = "select ndv(tag_id) from " + USER_TAG_TABLE_NAME + ";";
+ testMv(query, USER_TAG_MV_NAME);
}
/**
@@ -930,23 +920,43 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
// dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, "hll_union_agg");
}
- /**
- * TODO: enable this when hll is supported.
- */
@Test
public void testHLLUnionFamilyRewrite() throws Exception {
- // String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
- // + "`" + FunctionSet.HLL_UNION + "`(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME
- // + " group by user_id;";
- // createMv(createUserTagMVSql);
- // String query = "select `" + FunctionSet.HLL_UNION + "`(" + FunctionSet.HLL_HASH + "(tag_id)) from "
- // + USER_TAG_TABLE_NAME + ";";
- // String mvColumnName = CreateMaterializedViewStmt.mvColumnBuilder("" + FunctionSet.HLL_UNION + "", "tag_id");
- // dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, mvColumnName);
- // query = "select hll_union_agg(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME + ";";
- // dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, mvColumnName);
- // query = "select hll_raw_agg(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME + ";";
- // dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, mvColumnName);
+ String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
+ + "`" + FunctionSet.HLL_UNION + "`(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME
+ + " group by user_id;";
+ createMv(createUserTagMVSql);
+
+ String query = "select `" + FunctionSet.HLL_UNION + "`(" + FunctionSet.HLL_HASH + "(tag_id)) from "
+ + USER_TAG_TABLE_NAME + ";";
+ PlanChecker.from(connectContext)
+ .analyze(query)
+ .rewrite()
+ .matches(logicalAggregate().when(agg -> {
+ assertOneAggFuncType(agg, HllUnion.class);
+ return true;
+ }));
+ testMv(query, USER_TAG_MV_NAME);
+
+ query = "select hll_union_agg(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME + ";";
+ PlanChecker.from(connectContext)
+ .analyze(query)
+ .rewrite()
+ .matches(logicalAggregate().when(agg -> {
+ assertOneAggFuncType(agg, HllUnionAgg.class);
+ return true;
+ }));
+ testMv(query, USER_TAG_MV_NAME);
+
+ query = "select hll_raw_agg(" + FunctionSet.HLL_HASH + "(tag_id)) from " + USER_TAG_TABLE_NAME + ";";
+ PlanChecker.from(connectContext)
+ .analyze(query)
+ .rewrite()
+ .matches(logicalAggregate().when(agg -> {
+ assertOneAggFuncType(agg, HllUnion.class);
+ return true;
+ }));
+ testMv(query, USER_TAG_MV_NAME);
}
@Test
@@ -958,41 +968,20 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
testMv(query, EMPS_TABLE_NAME);
}
- /**
- * TODO: support count in mv.
- */
- @Disabled
+ @Test
public void testCountFieldInQuery() throws Exception {
- // String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
- // + "count(tag_id) from " + USER_TAG_TABLE_NAME + " group by user_id;";
- // createMv(createUserTagMVSql);
- // String query = "select count(tag_id) from " + USER_TAG_TABLE_NAME + ";";
- // String mvColumnName = CreateMaterializedViewStmt.mvColumnBuilder(FunctionSet.COUNT, "tag_id");
- // // dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, mvColumnName);
- //
- // String explain = getSQLPlanOrErrorMsg(query);
- // mv_count_tag_id
- /*
- PARTITION: HASH_PARTITIONED: `default_cluster:db1`.`user_tags`.`time_col`
-
- STREAM DATA SINK
- EXCHANGE ID: 02
- UNPARTITIONED
-
- 1:VAGGREGATE (update serialize)
- | output: sum(`mv_count_tag_id`)
- | group by:
- | cardinality=1
- |
- 0:VOlapScanNode
- TABLE: user_tags(user_tags_mv), PREAGGREGATION: ON
- partitions=1/1, tablets=3/3, tabletList=10034,10036,10038
- cardinality=0, avgRowSize=8.0, numNodes=1
- */
- // System.out.println("mvColumnName:" + mvColumnName);
- // System.out.println("explain:\n" + explain);
- // query = "select user_name, count(tag_id) from " + USER_TAG_TABLE_NAME + " group by user_name;";
- // dorisAssert.query(query).explainWithout(USER_TAG_MV_NAME);
+ String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
+ + "count(tag_id) from " + USER_TAG_TABLE_NAME + " group by user_id;";
+ createMv(createUserTagMVSql);
+ String query = "select count(tag_id) from " + USER_TAG_TABLE_NAME + ";";
+ PlanChecker.from(connectContext)
+ .analyze(query)
+ .rewrite()
+ .matches(logicalAggregate().when(agg -> {
+ assertOneAggFuncType(agg, Sum.class);
+ return true;
+ }));
+ testMv(query, USER_TAG_MV_NAME);
}
@Test
@@ -1013,17 +1002,20 @@ public class SelectMvIndexTest extends BaseMaterializedIndexSelectTest implement
dropTable("agg_table", true);
}
- /**
- * TODO: support count in mv.
- */
- @Disabled
+ @Test
public void testSelectMVWithTableAlias() throws Exception {
- // String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
- // + "count(tag_id) from " + USER_TAG_TABLE_NAME + " group by user_id;";
- // dorisAssert.withMaterializedView(createUserTagMVSql);
- // String query = "select count(tag_id) from " + USER_TAG_TABLE_NAME + " t ;";
- // String mvColumnName = CreateMaterializedViewStmt.mvColumnBuilder(FunctionSet.COUNT, "tag_id");
- // dorisAssert.query(query).explainContains(USER_TAG_MV_NAME, mvColumnName);
+ String createUserTagMVSql = "create materialized view " + USER_TAG_MV_NAME + " as select user_id, "
+ + "count(tag_id) from " + USER_TAG_TABLE_NAME + " group by user_id;";
+ createMv(createUserTagMVSql);
+ String query = "select count(tag_id) from " + USER_TAG_TABLE_NAME + " t ;";
+ PlanChecker.from(connectContext)
+ .analyze(query)
+ .rewrite()
+ .matches(logicalAggregate().when(agg -> {
+ assertOneAggFuncType(agg, Sum.class);
+ return true;
+ }));
+ testMv(query, USER_TAG_MV_NAME);
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org