This is an automated email from the ASF dual-hosted git repository.

kangkaisen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new f516172  Fix window function with limit zero bug 2 (#4235)
f516172 is described below

commit f516172f2303168e4e26d6ae25f4e0289c830010
Author: kangkaisen <kangkai...@apache.org>
AuthorDate: Mon Aug 10 10:29:05 2020 +0800

    Fix window function with limit zero bug 2 (#4235)
---
 .../java/org/apache/doris/analysis/SelectStmt.java |  8 +++++
 .../apache/doris/planner/SingleNodePlanner.java    | 38 +++++++++-------------
 .../org/apache/doris/planner/QueryPlanTest.java    | 28 ++++++++++++++++
 3 files changed, 52 insertions(+), 22 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java
index f2b057a..405490c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SelectStmt.java
@@ -1567,6 +1567,13 @@ public class SelectStmt extends QueryStmt {
         return strBuilder.toString();
     }
 
+    /**
+     * If the select statement has a sort/top that is evaluated, then the sort 
tuple
+     * is materialized. Else, if there is aggregation then the aggregate tuple 
id is
+     * materialized. Otherwise, all referenced tables are materialized as long 
as they are
+     * not semi-joined. If there are analytics and no sort, then the returned 
tuple
+     * ids also include the logical analytic output tuple.
+     */
     @Override
     public void getMaterializedTupleIds(ArrayList<TupleId> tupleIdList) {
         // If select statement has an aggregate, then the aggregate tuple id 
is materialized.
@@ -1585,6 +1592,7 @@ public class SelectStmt extends QueryStmt {
                 tupleIdList.addAll(tblRef.getMaterializedTupleIds());
             }
         }
+        // Fixme(kks): get tuple id from analyticInfo is wrong, should get 
from AnalyticEvalNode
         // We materialize the agg tuple or the table refs together with the 
analytic tuple.
         if (hasAnalyticInfo() && isEvaluateOrderBy()) {
             tupleIdList.add(analyticInfo.getOutputTupleId());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
index 1a569a5..d67616a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
@@ -208,27 +208,6 @@ public class SingleNodePlanner {
      */
     private PlanNode createQueryPlan(QueryStmt stmt, Analyzer analyzer, long 
defaultOrderByLimit)
             throws UserException {
-        if (analyzer.hasEmptyResultSet()) {
-            PlanNode node = createEmptyNode(stmt, analyzer);
-
-            // handle window function with limit zero
-            if (stmt instanceof SelectStmt) {
-                SelectStmt selectStmt = (SelectStmt) stmt;
-                if (selectStmt.getAnalyticInfo() != null) {
-                    AnalyticInfo analyticInfo = selectStmt.getAnalyticInfo();
-                    AnalyticPlanner analyticPlanner = new 
AnalyticPlanner(analyticInfo, analyzer, ctx_);
-                    List<Expr> inputPartitionExprs = Lists.newArrayList();
-                    AggregateInfo aggInfo = selectStmt.getAggInfo();
-                    PlanNode root = analyticPlanner.createSingleNodePlan(node,
-                            aggInfo != null ? aggInfo.getGroupingExprs() : 
null, inputPartitionExprs);
-
-                    // In order to substitute the analytic expr with slot in 
result exprs
-                    node.setOutputSmap(root.outputSmap);
-                }
-            }
-            return node;
-        }
-
         long newDefaultOrderByLimit = defaultOrderByLimit;
         if (newDefaultOrderByLimit == -1) {
             newDefaultOrderByLimit = 65535;
@@ -300,6 +279,21 @@ public class SingleNodePlanner {
         if (stmt.getAssertNumRowsElement() != null) {
             root = createAssertRowCountNode(root, 
stmt.getAssertNumRowsElement(), analyzer);
         }
+
+        if (analyzer.hasEmptyResultSet()) {
+            // Must clear the scanNodes, otherwise we will get NPE in 
Coordinator::computeScanRangeAssignment
+            scanNodes.clear();
+            PlanNode node = createEmptyNode(stmt, analyzer);
+            // Ensure result exprs will be substituted by right outputSmap
+            node.setOutputSmap(root.outputSmap);
+            // Currently, getMaterializedTupleIds for AnalyticEvalNode is 
wrong,
+            // So we explicitly add AnalyticEvalNode tuple ids to EmptySetNode
+            if (root instanceof AnalyticEvalNode) {
+                node.getTupleIds().addAll(root.tupleIds);
+            }
+            return node;
+        }
+
         return root;
     }
 
@@ -687,7 +681,7 @@ public class SingleNodePlanner {
             rowTuples.addAll(tblRef.getMaterializedTupleIds());
         }
 
-        if (analyzer.hasEmptySpjResultSet()) {
+        if (analyzer.hasEmptySpjResultSet() && selectStmt.getAggInfo() != 
null) {
             final PlanNode emptySetNode = new 
EmptySetNode(ctx_.getNextNodeId(), rowTuples);
             emptySetNode.init(analyzer);
             emptySetNode.setOutputSmap(selectStmt.getBaseTblSmap());
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
index b9eb997..ff2bc62 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.planner;
 
+import com.google.common.collect.Lists;
 import org.apache.doris.analysis.CreateDbStmt;
 import org.apache.doris.analysis.CreateTableStmt;
 import org.apache.doris.analysis.DropDbStmt;
@@ -969,4 +970,31 @@ public class QueryPlanTest {
         explainString = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, 
queryStr);
         Assert.assertTrue(explainString.contains("INNER JOIN (BROADCAST)"));
     }
+
+    @Test
+    public void testEmptyNode() throws Exception {
+        connectContext.setDatabase("default_cluster:test");
+        String emptyNode = "EMPTYSET";
+        String denseRank = "dense_rank";
+
+        List<String> sqls = Lists.newArrayList();
+        sqls.add("explain select * from baseall limit 0");
+        sqls.add("explain select count(*) from baseall limit 0;");
+        sqls.add("explain select k3, dense_rank() OVER () AS rank FROM baseall 
limit 0;");
+        sqls.add("explain select rank from (select k3, dense_rank() OVER () AS 
rank FROM baseall) a limit 0;");
+        sqls.add("explain select * from baseall join bigtable as b limit 0");
+
+        sqls.add("explain select * from baseall where 1 = 2");
+        sqls.add("explain select count(*) from baseall where 1 = 2;");
+        sqls.add("explain select k3, dense_rank() OVER () AS rank FROM baseall 
where 1 =2;");
+        sqls.add("explain select rank from (select k3, dense_rank() OVER () AS 
rank FROM baseall) a where 1 =2;");
+        sqls.add("explain select * from baseall join bigtable as b where 1 = 
2");
+
+        for(String sql: sqls) {
+            String explainString = 
UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, sql);
+            System.out.println(explainString);
+            Assert.assertTrue(explainString.contains(emptyNode));
+            Assert.assertFalse(explainString.contains(denseRank));
+        }
+    }
 }


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

Reply via email to