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 b45f501e511 [improvement](nereids) Support aggregate functions without 
from clause (#25500)
b45f501e511 is described below

commit b45f501e51145de5c52d2ee0201175133f0317a6
Author: JingDas <114388747+jing...@users.noreply.github.com>
AuthorDate: Thu Oct 19 12:07:37 2023 +0800

    [improvement](nereids) Support aggregate functions without from clause 
(#25500)
    
    Support aggregate functions in select without from clause, here are some 
examples as following:
    
    SELECT 1,
      'a',
       COUNT(),
       SUM(1) + 1,
       AVG(2) / COUNT(),
       MAX(3),
       MIN(4),
       RANK() OVER() AS w_rank,
       DENSE_RANK() OVER() AS w_dense_rank,
       ROW_NUMBER() OVER() AS w_row_number,
       SUM(5) OVER() AS w_sum,
       AVG(6) OVER() AS w_avg,
       COUNT() OVER() AS w_count,
       MAX(7) OVER() AS w_max,
       MIN(8) OVER() AS w_min;
---
 .../doris/nereids/jobs/executor/Analyzer.java      |  4 +-
 .../org/apache/doris/nereids/rules/RuleType.java   |  1 +
 .../nereids/rules/analysis/CheckAnalysis.java      |  1 -
 .../analysis/OneRowRelationExtractAggregate.java   | 68 ++++++++++++++++++++++
 .../rules/analysis/ProjectToGlobalAggregate.java   | 35 +----------
 .../doris/nereids/rules/rewrite/ColumnPruning.java |  3 +
 .../expressions/visitor/ExpressionVisitors.java}   | 45 ++------------
 .../trees/plans/logical/LogicalOneRowRelation.java |  4 --
 .../select_no_from/sql/projectAggFuncs.out         |  4 ++
 .../select_no_from/sql/projectAggFuncs.out         |  4 ++
 .../select_no_from/sql/projectAggFuncs.sql         | 19 +++++-
 .../nereids_syntax_p0/one_row_relation.groovy      |  7 ---
 .../select_no_from/sql/projectAggFuncs.sql         | 18 +++++-
 13 files changed, 122 insertions(+), 91 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
index 333fc8a16de..e773ed41f60 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
@@ -34,6 +34,7 @@ import 
org.apache.doris.nereids.rules.analysis.EliminateGroupByConstant;
 import org.apache.doris.nereids.rules.analysis.FillUpMissingSlots;
 import org.apache.doris.nereids.rules.analysis.NormalizeAggregate;
 import org.apache.doris.nereids.rules.analysis.NormalizeRepeat;
+import org.apache.doris.nereids.rules.analysis.OneRowRelationExtractAggregate;
 import org.apache.doris.nereids.rules.analysis.ProjectToGlobalAggregate;
 import org.apache.doris.nereids.rules.analysis.ProjectWithDistinctToAggregate;
 import org.apache.doris.nereids.rules.analysis.ReplaceExpressionByChildOutput;
@@ -103,7 +104,8 @@ public class Analyzer extends AbstractBatchJobExecutor {
                 // please see rule BindSlotReference or BindFunction for 
example
                 new ProjectWithDistinctToAggregate(),
                 new ResolveOrdinalInOrderByAndGroupBy(),
-                new ReplaceExpressionByChildOutput()
+                new ReplaceExpressionByChildOutput(),
+                new OneRowRelationExtractAggregate()
             ),
             topDown(
                 new FillUpMissingSlots(),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
index 617cb352908..f3b862f0c6d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
@@ -71,6 +71,7 @@ public enum RuleType {
     RESOLVE_PROJECT_ALIAS(RuleTypeClass.REWRITE),
     RESOLVE_AGGREGATE_ALIAS(RuleTypeClass.REWRITE),
     PROJECT_TO_GLOBAL_AGGREGATE(RuleTypeClass.REWRITE),
+    ONE_ROW_RELATION_EXTRACT_AGGREGATE(RuleTypeClass.REWRITE),
     PROJECT_WITH_DISTINCT_TO_AGGREGATE(RuleTypeClass.REWRITE),
     AVG_DISTINCT_TO_SUM_DIV_COUNT(RuleTypeClass.REWRITE),
     ANALYZE_CTE(RuleTypeClass.REWRITE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAnalysis.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAnalysis.java
index d32823799e2..fc6ddfcf79b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAnalysis.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAnalysis.java
@@ -76,7 +76,6 @@ public class CheckAnalysis implements AnalysisRuleFactory {
                     TableGeneratingFunction.class,
                     WindowExpression.class))
             .put(LogicalOneRowRelation.class, ImmutableSet.of(
-                    AggregateFunction.class,
                     GroupingScalarFunction.class,
                     TableGeneratingFunction.class,
                     WindowExpression.class))
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/OneRowRelationExtractAggregate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/OneRowRelationExtractAggregate.java
new file mode 100644
index 00000000000..37aaf22ce76
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/OneRowRelationExtractAggregate.java
@@ -0,0 +1,68 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.rules.analysis;
+
+import org.apache.doris.nereids.rules.Rule;
+import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitors;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.nereids.trees.plans.logical.LogicalOneRowRelation;
+import org.apache.doris.nereids.trees.plans.logical.LogicalRelation;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * OneRowRelationExtractAggregate.
+ * <p>
+ * example sql:
+ * <pre>
+ * SELECT 1, 'a', COUNT();
+ * </pre>
+ * <p>
+ * origin plan:
+ * <p>
+ * LogicalOneRowRelation ( projects=[1 AS `1`#0, 'a' AS `'a'`#1, count(*) AS 
`count(*)`#2] )
+ * transformed plan:
+ * <p>
+ * LogicalAggregate[23] ( groupByExpr=[], outputExpr=[1 AS `1`#0, 'a' AS 
`'a'`#1, count(*) AS `count(*)`#2],
+ *     hasRepeat=false )
+ * LogicalOneRowRelation ( projects=[] )
+ */
+public class OneRowRelationExtractAggregate extends OneAnalysisRuleFactory {
+    @Override
+    public Rule build() {
+        return RuleType.ONE_ROW_RELATION_EXTRACT_AGGREGATE.build(
+                logicalOneRowRelation().then(relation -> {
+                    List<NamedExpression> outputs = relation.getOutputs();
+                    boolean needGlobalAggregate = outputs
+                            .stream()
+                            .anyMatch(p -> 
p.accept(ExpressionVisitors.CONTAINS_AGGREGATE_CHECKER, null));
+                    if (needGlobalAggregate) {
+                        LogicalRelation newRelation = new 
LogicalOneRowRelation(relation.getRelationId(),
+                                ImmutableList.of());
+                        return new LogicalAggregate<>(ImmutableList.of(), 
relation.getOutputs(), newRelation);
+                    } else {
+                        return relation;
+                    }
+                })
+        );
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
index 66371ae0006..da642e76610 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
@@ -19,10 +19,7 @@ package org.apache.doris.nereids.rules.analysis;
 
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.trees.expressions.Expression;
-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.visitor.DefaultExpressionVisitor;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitors;
 import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
 
 import com.google.common.collect.ImmutableList;
@@ -49,7 +46,7 @@ public class ProjectToGlobalAggregate extends 
OneAnalysisRuleFactory {
            logicalProject().then(project -> {
                boolean needGlobalAggregate = project.getProjects()
                        .stream()
-                       .anyMatch(p -> 
p.accept(ContainsAggregateChecker.INSTANCE, null));
+                       .anyMatch(p -> 
p.accept(ExpressionVisitors.CONTAINS_AGGREGATE_CHECKER, null));
 
                if (needGlobalAggregate) {
                    return new LogicalAggregate<>(ImmutableList.of(), 
project.getProjects(), project.child());
@@ -59,32 +56,4 @@ public class ProjectToGlobalAggregate extends 
OneAnalysisRuleFactory {
            })
         );
     }
-
-    private static class ContainsAggregateChecker extends 
DefaultExpressionVisitor<Boolean, Void> {
-
-        private static final ContainsAggregateChecker INSTANCE = new 
ContainsAggregateChecker();
-
-        @Override
-        public Boolean visit(Expression expr, Void context) {
-            boolean needAggregate = false;
-            for (Expression child : expr.children()) {
-                needAggregate = needAggregate || child.accept(this, context);
-            }
-            return needAggregate;
-        }
-
-        @Override
-        public Boolean visitWindow(WindowExpression windowExpression, Void 
context) {
-            boolean needAggregate = false;
-            for (Expression child : 
windowExpression.getExpressionsInWindowSpec()) {
-                needAggregate = needAggregate || child.accept(this, context);
-            }
-            return needAggregate;
-        }
-
-        @Override
-        public Boolean visitAggregateFunction(AggregateFunction 
aggregateFunction, Void context) {
-            return true;
-        }
-    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ColumnPruning.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ColumnPruning.java
index 375ce34e6a8..32e9cf64b67 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ColumnPruning.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/ColumnPruning.java
@@ -215,6 +215,9 @@ public class ColumnPruning extends 
DefaultPlanRewriter<PruneContext> implements
     /** prune output */
     public static <P extends Plan> P pruneOutput(P plan, List<NamedExpression> 
originOutput,
             Function<List<NamedExpression>, P> withPrunedOutput, PruneContext 
context) {
+        if (originOutput.isEmpty()) {
+            return plan;
+        }
         List<NamedExpression> prunedOutputs = originOutput.stream()
                 .filter(output -> 
context.requiredSlots.contains(output.toSlot()))
                 .collect(ImmutableList.toImmutableList());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitors.java
similarity index 55%
copy from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
copy to 
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitors.java
index 66371ae0006..513da0e93d9 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ProjectToGlobalAggregate.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitors.java
@@ -15,55 +15,22 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.rules.analysis;
+package org.apache.doris.nereids.trees.expressions.visitor;
 
-import org.apache.doris.nereids.rules.Rule;
-import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.expressions.Expression;
 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.visitor.DefaultExpressionVisitor;
-import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
-
-import com.google.common.collect.ImmutableList;
 
 /**
- * ProjectToGlobalAggregate.
- * <p>
- * example sql:
- * <pre>
- * select sum(value)
- * from tbl
- * </pre>
- *
- * origin plan:                                                 transformed 
plan:
- * <p>
- * LogicalProject(projects=[sum(value)])                        
LogicalAggregate(groupBy=[], output=[sum(value)])
- *            |                                      =>                        
      |
- *  LogicalOlapScan(table=tbl)                                                 
 LogicalOlapScan(table=tbl)
+ * This is the factory for all ExpressionVisitor instance.
+ * All children instance of DefaultExpressionVisitor or ExpressionVisitor for 
common usage
+ * should be here and expose self by class static final field.
  */
-public class ProjectToGlobalAggregate extends OneAnalysisRuleFactory {
-    @Override
-    public Rule build() {
-        return RuleType.PROJECT_TO_GLOBAL_AGGREGATE.build(
-           logicalProject().then(project -> {
-               boolean needGlobalAggregate = project.getProjects()
-                       .stream()
-                       .anyMatch(p -> 
p.accept(ContainsAggregateChecker.INSTANCE, null));
+public class ExpressionVisitors {
 
-               if (needGlobalAggregate) {
-                   return new LogicalAggregate<>(ImmutableList.of(), 
project.getProjects(), project.child());
-               } else {
-                   return project;
-               }
-           })
-        );
-    }
+    public static final ContainsAggregateChecker CONTAINS_AGGREGATE_CHECKER = 
new ContainsAggregateChecker();
 
     private static class ContainsAggregateChecker extends 
DefaultExpressionVisitor<Boolean, Void> {
-
-        private static final ContainsAggregateChecker INSTANCE = new 
ContainsAggregateChecker();
-
         @Override
         public Boolean visit(Expression expr, Void context) {
             boolean needAggregate = false;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOneRowRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOneRowRelation.java
index 68351c9a902..ffc7c0d625a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOneRowRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOneRowRelation.java
@@ -22,7 +22,6 @@ import org.apache.doris.nereids.properties.LogicalProperties;
 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.plans.Plan;
 import org.apache.doris.nereids.trees.plans.PlanType;
 import org.apache.doris.nereids.trees.plans.RelationId;
@@ -30,7 +29,6 @@ import 
org.apache.doris.nereids.trees.plans.algebra.OneRowRelation;
 import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
 import org.apache.doris.nereids.util.Utils;
 
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 import java.util.List;
@@ -52,8 +50,6 @@ public class LogicalOneRowRelation extends LogicalRelation 
implements OneRowRela
     private LogicalOneRowRelation(RelationId relationId, List<NamedExpression> 
projects,
             Optional<GroupExpression> groupExpression, 
Optional<LogicalProperties> logicalProperties) {
         super(relationId, PlanType.LOGICAL_ONE_ROW_RELATION, groupExpression, 
logicalProperties);
-        Preconditions.checkArgument(projects.stream().noneMatch(p -> 
p.containsType(AggregateFunction.class)),
-                "OneRowRelation can not contains any aggregate function");
         this.projects = ImmutableList.copyOf(Objects.requireNonNull(projects, 
"projects can not be null"));
     }
 
diff --git 
a/regression-test/data/nereids_p0/select_no_from/sql/projectAggFuncs.out 
b/regression-test/data/nereids_p0/select_no_from/sql/projectAggFuncs.out
new file mode 100644
index 00000000000..7ae8fd347ed
--- /dev/null
+++ b/regression-test/data/nereids_p0/select_no_from/sql/projectAggFuncs.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !projectAggFuncs --
+1      a       1       2       2.0     3       4       1       1       1       
5       6.0     1       7       8
+
diff --git 
a/regression-test/data/query_p0/select_no_from/sql/projectAggFuncs.out 
b/regression-test/data/query_p0/select_no_from/sql/projectAggFuncs.out
new file mode 100644
index 00000000000..7ae8fd347ed
--- /dev/null
+++ b/regression-test/data/query_p0/select_no_from/sql/projectAggFuncs.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !projectAggFuncs --
+1      a       1       2       2.0     3       4       1       1       1       
5       6.0     1       7       8
+
diff --git 
a/regression-test/suites/nereids_p0/select_no_from/sql/projectAggFuncs.sql 
b/regression-test/suites/nereids_p0/select_no_from/sql/projectAggFuncs.sql
index 50c3d56ed8f..d2416eb991c 100644
--- a/regression-test/suites/nereids_p0/select_no_from/sql/projectAggFuncs.sql
+++ b/regression-test/suites/nereids_p0/select_no_from/sql/projectAggFuncs.sql
@@ -1,4 +1,17 @@
-/*
 -- database: presto; groups: no_from
-SELECT COUNT(10), MAX(50), MIN(90.0)
-*/
+SELECT 1,
+       'a',
+       COUNT(),
+       SUM(1) + 1,
+       AVG(2) / COUNT(),
+       MAX(3),
+       MIN(4),
+       RANK() OVER() AS w_rank,
+        DENSE_RANK() OVER() AS w_dense_rank,
+        ROW_NUMBER() OVER() AS w_row_number,
+        SUM(5) OVER() AS w_sum,
+        AVG(6) OVER() AS w_avg,
+        COUNT() OVER() AS w_count,
+        MAX(7) OVER() AS w_max,
+        MIN(8) OVER() AS w_min;
+
diff --git a/regression-test/suites/nereids_syntax_p0/one_row_relation.groovy 
b/regression-test/suites/nereids_syntax_p0/one_row_relation.groovy
index 9b814cc4fe0..e389960e79e 100644
--- a/regression-test/suites/nereids_syntax_p0/one_row_relation.groovy
+++ b/regression-test/suites/nereids_syntax_p0/one_row_relation.groovy
@@ -31,11 +31,4 @@ suite("one_row_relation") {
         )a"""
         result([[100, "abc", "ab", "de", null]])
     }
-
-    test {
-        sql """
-            select sum(1);
-        """
-        exception "OneRowRelation can not contains any aggregate function"     
       
-    }
 }
diff --git 
a/regression-test/suites/query_p0/select_no_from/sql/projectAggFuncs.sql 
b/regression-test/suites/query_p0/select_no_from/sql/projectAggFuncs.sql
index 50c3d56ed8f..a0007ff2df7 100644
--- a/regression-test/suites/query_p0/select_no_from/sql/projectAggFuncs.sql
+++ b/regression-test/suites/query_p0/select_no_from/sql/projectAggFuncs.sql
@@ -1,4 +1,16 @@
-/*
 -- database: presto; groups: no_from
-SELECT COUNT(10), MAX(50), MIN(90.0)
-*/
+SELECT 1,
+       'a',
+       COUNT(),
+       SUM(1) + 1,
+       AVG(2) / COUNT(),
+       MAX(3),
+       MIN(4),
+       RANK() OVER() AS w_rank,
+       DENSE_RANK() OVER() AS w_dense_rank,
+       ROW_NUMBER() OVER() AS w_row_number,
+       SUM(5) OVER() AS w_sum,
+       AVG(6) OVER() AS w_avg,
+       COUNT() OVER() AS w_count,
+       MAX(7) OVER() AS w_max,
+       MIN(8) OVER() AS w_min;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to