This is an automated email from the ASF dual-hosted git repository. morningman 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 1d900d8 (fix)[planner] Fix the right tuple ids in empty set node (#7931) 1d900d8 is described below commit 1d900d8605d41604762c50ea0e2eb909f0c31f27 Author: EmmyMiao87 <522274...@qq.com> AuthorDate: Sat Jan 29 09:46:05 2022 +0800 (fix)[planner] Fix the right tuple ids in empty set node (#7931) The tuple ids of the empty set node must be exactly the same as the tuple ids of the origin root node. In the issue, we found that once the tree where the root node is located has a window function, the tuple ids of the empty set node cannot be calculated correctly. This pr mostly fixes the problem. In order to calculate the correct tuple ids, the tuple ids obtained from the SelectStmt.getMaterializedTupleIds() function in the past are changed to directly use the tuple ids of the origin root node. Although we tried to fix #7929 by modifying the SelectStmt.getMaterializedTupleIds() function, this method can't get the tuple of the last correct window function. So we use other ways to construct tupleids of empty nodes. --- be/src/runtime/descriptors.cpp | 2 +- .../java/org/apache/doris/analysis/SelectStmt.java | 5 +-- .../apache/doris/planner/SingleNodePlanner.java | 17 ++++------ .../org/apache/doris/planner/QueryPlanTest.java | 38 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/be/src/runtime/descriptors.cpp b/be/src/runtime/descriptors.cpp index 95d0a79..2e7041b 100644 --- a/be/src/runtime/descriptors.cpp +++ b/be/src/runtime/descriptors.cpp @@ -370,7 +370,7 @@ int RowDescriptor::get_row_size() const { } int RowDescriptor::get_tuple_idx(TupleId id) const { - DCHECK_LT(id, _tuple_idx_map.size()) << "RowDescriptor: " << debug_string(); + CHECK_LT(id, _tuple_idx_map.size()) << "RowDescriptor: " << debug_string(); return _tuple_idx_map[id]; } 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 1c52f12..240d8ea 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 @@ -1732,9 +1732,10 @@ public class SelectStmt extends QueryStmt { tupleIdList.addAll(tblRef.getMaterializedTupleIds()); } } - // Fixme(kks): get tuple id from analyticInfo is wrong, should get from AnalyticEvalNode + // Fixme(ml): get tuple id from analyticInfo is wrong, should get from AnalyticEvalNode + // Fixme(ml): The tuple id of AnalyticEvalNode actually is the physical output tuple from analytic planner // We materialize the agg tuple or the table refs together with the analytic tuple. - if (hasAnalyticInfo() && isEvaluateOrderBy()) { + 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 f62f606..3b4dba7 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 @@ -60,6 +60,7 @@ import org.apache.doris.common.FeConstants; import org.apache.doris.common.Pair; import org.apache.doris.common.Reference; import org.apache.doris.common.UserException; +import org.apache.doris.common.util.VectorizedUtil; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; @@ -68,7 +69,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import org.apache.doris.common.util.VectorizedUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -174,9 +174,11 @@ public class SingleNodePlanner { * they are never unnested, and therefore the corresponding parent scan should not * materialize them. */ - private PlanNode createEmptyNode(QueryStmt stmt, Analyzer analyzer) { + private PlanNode createEmptyNode(PlanNode inputPlan, QueryStmt stmt, Analyzer analyzer) { ArrayList<TupleId> tupleIds = Lists.newArrayList(); - stmt.getMaterializedTupleIds(tupleIds); + if (inputPlan != null) { + tupleIds = inputPlan.tupleIds; + } if (tupleIds.isEmpty()) { // Constant selects do not have materialized tuples at this stage. Preconditions.checkState(stmt instanceof SelectStmt, @@ -298,14 +300,9 @@ public class SingleNodePlanner { // Must clear the scanNodes, otherwise we will get NPE in Coordinator::computeScanRangeAssignment Set<TupleId> scanTupleIds = new HashSet<>(root.getAllScanTupleIds()); scanNodes.removeIf(scanNode -> scanTupleIds.contains(scanNode.getTupleIds().get(0))); - PlanNode node = createEmptyNode(stmt, analyzer); + PlanNode node = createEmptyNode(root, 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; } @@ -1327,7 +1324,7 @@ public class SingleNodePlanner { SelectStmt selectStmt = (SelectStmt) viewStmt; if (selectStmt.getTableRefs().isEmpty()) { if (inlineViewRef.getAnalyzer().hasEmptyResultSet()) { - PlanNode emptySetNode = createEmptyNode(viewStmt, inlineViewRef.getAnalyzer()); + PlanNode emptySetNode = createEmptyNode(null, viewStmt, inlineViewRef.getAnalyzer()); // Still substitute exprs in parent nodes with the inline-view's smap to make // sure no exprs reference the non-materialized inline view slots. No wrapping // with TupleIsNullPredicates is necessary here because we do not migrate 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 5df684b..1d3a588 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 @@ -1824,4 +1824,42 @@ public class QueryPlanTest { Assert.assertTrue(explainStr.contains("PREDICATES: `date` >= '2021-10-07 00:00:00', `date` <= '2021-10-11 00:00:00'")); } + // Fix: issue-#7929 + @Test + public void testEmptyNodeWithOuterJoinAndAnalyticFunction() throws Exception { + // create database + String createDbStmtStr = "create database issue7929;"; + CreateDbStmt createDbStmt = (CreateDbStmt) UtFrameUtils.parseAndAnalyzeStmt(createDbStmtStr, connectContext); + Catalog.getCurrentCatalog().createDb(createDbStmt); + createTable(" CREATE TABLE issue7929.`t1` (\n" + + " `k1` int(11) NULL COMMENT \"\",\n" + + " `k2` int(11) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`k1`, `k2`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`k1`) BUCKETS 1\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ")"); + createTable("CREATE TABLE issue7929.`t2` (\n" + + " `j1` int(11) NULL COMMENT \"\",\n" + + " `j2` int(11) NULL COMMENT \"\"\n" + + ") ENGINE=OLAP\n" + + "DUPLICATE KEY(`j1`, `j2`)\n" + + "COMMENT \"OLAP\"\n" + + "DISTRIBUTED BY HASH(`j1`) BUCKETS 1\n" + + "PROPERTIES (\n" + + "\"replication_allocation\" = \"tag.location.default: 1\",\n" + + "\"in_memory\" = \"false\",\n" + + "\"storage_format\" = \"V2\"\n" + + ")"); + String sql = "select * from issue7929.t1 left join (select max(j1) over() as x from issue7929.t2)a on t1.k1=a.x where 1=0;"; + String explainStr = UtFrameUtils.getSQLPlanOrErrorMsg(connectContext, sql, true); + Assert.assertTrue(explainStr.contains("4:EMPTYSET")); + Assert.assertTrue(explainStr.contains("tuple ids: 0 1 5")); + + } + } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org