From 6bb111b42c754d35da3414abc940f363d4bf31d6 Mon Sep 17 00:00:00 2001 From: EmmyMiao87 <522274284@qq.com> Date: Thu, 20 Aug 2020 09:30:35 +0800 Subject: [PATCH] Modify mv rewrite rule on 'Count distinct' (#4382) The rewrite rule named `CountToSum` does not distinguish between `Count` and `Count distinct` which causes `Count distinct` is rewritten as `Sum` incorrectly. So this commit modified matching rule. When the function is `Count distinct`, the rewrite rule will not take effect. Fixed #4381 --- .../rewrite/mvrewrite/CountFieldToSum.java | 3 + .../mvrewrite/CountFieldToSumTest.java | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 fe/fe-core/src/test/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSumTest.java diff --git a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSum.java b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSum.java index 4f55a9b85d..b13b5deec0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSum.java +++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSum.java @@ -60,6 +60,9 @@ public class CountFieldToSum implements ExprRewriteRule { if (fnExpr.getChildren().size() != 1 || !(fnExpr.getChild(0) instanceof SlotRef)) { return expr; } + if (fnExpr.getParams().isDistinct()) { + return expr; + } SlotRef fnChild0 = (SlotRef) fnExpr.getChild(0); Column column = fnChild0.getColumn(); Table table = fnChild0.getTable(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSumTest.java b/fe/fe-core/src/test/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSumTest.java new file mode 100644 index 0000000000..5ceaf00b95 --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/rewrite/mvrewrite/CountFieldToSumTest.java @@ -0,0 +1,69 @@ +// 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.rewrite.mvrewrite; + +import org.apache.doris.analysis.Analyzer; +import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.FunctionCallExpr; +import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.TableName; +import org.apache.doris.catalog.FunctionSet; +import org.apache.doris.common.AnalysisException; + +import com.google.common.collect.Lists; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +import mockit.Expectations; +import mockit.Injectable; + +public class CountFieldToSumTest { + + @Test + public void testCountDistinct(@Injectable Analyzer analyzer, + @Injectable FunctionCallExpr functionCallExpr) { + TableName tableName = new TableName("db1", "table1"); + SlotRef slotRef = new SlotRef(tableName,"c1"); + List params = Lists.newArrayList(); + params.add(slotRef); + + new Expectations() { + { + functionCallExpr.getFnName().getFunction(); + result = FunctionSet.COUNT; + functionCallExpr.getChildren(); + result = params; + functionCallExpr.getChild(0); + result = slotRef; + functionCallExpr.getParams().isDistinct(); + result = true; + } + }; + CountFieldToSum countFieldToSum = new CountFieldToSum(); + try { + Expr rewrittenExpr = countFieldToSum.apply(functionCallExpr, analyzer); + Assert.assertTrue(rewrittenExpr instanceof FunctionCallExpr); + Assert.assertEquals(FunctionSet.COUNT, ((FunctionCallExpr) rewrittenExpr).getFnName().getFunction()); + } catch (AnalysisException e) { + System.out.println(e.getMessage()); + } + } +}