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 2e651bbc9a [fix](nereids) fix some planner bugs (#21533) 2e651bbc9a is described below commit 2e651bbc9a88de1ca99060a15281711660137d37 Author: starocean999 <40539150+starocean...@users.noreply.github.com> AuthorDate: Thu Jul 6 16:13:37 2023 +0800 [fix](nereids) fix some planner bugs (#21533) 1. allow cast boolean as date like type in nereids, the result is null 2. PruneOlapScanTablet rule can prune tablet even if a mv index is selected. 3. constant conjunct should not be pushed through agg node in old planner --- .../java/org/apache/doris/analysis/Analyzer.java | 6 +- .../nereids/rules/expression/check/CheckCast.java | 12 ++-- .../nereids/rules/rewrite/PruneOlapScanTablet.java | 12 ++-- .../doris/planner/HashDistributionPruner.java | 12 +++- .../org/apache/doris/planner/OlapScanNode.java | 3 +- .../doris/planner/HashDistributionPrunerTest.java | 2 +- .../org/apache/doris/planner/OlapScanNodeTest.java | 6 +- .../data/correctness_p0/test_constant_having.out | 5 ++ .../correctness_p0/test_constant_having.groovy | 74 ++++++++++++++++++++++ .../suites/nereids_p0/datatype/test_cast.groovy | 20 ++++++ .../suites/nereids_p0/test_prune_tablet_mv.groovy | 45 +++++++++++++ 11 files changed, 177 insertions(+), 20 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java index 0faa84d2e4..33aa53412b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java @@ -40,6 +40,7 @@ import org.apache.doris.common.ErrorReport; import org.apache.doris.common.IdGenerator; import org.apache.doris.common.Pair; import org.apache.doris.common.util.TimeUtils; +import org.apache.doris.planner.AggregationNode; import org.apache.doris.planner.PlanNode; import org.apache.doris.planner.RuntimeFilter; import org.apache.doris.qe.ConnectContext; @@ -2416,10 +2417,11 @@ public class Analyzer { * Wrapper around getUnassignedConjuncts(List<TupleId> tupleIds). */ public List<Expr> getUnassignedConjuncts(PlanNode node) { - // constant conjuncts should be push down to all leaf node. + // constant conjuncts should be push down to all leaf node except agg node. + // (see getPredicatesBoundedByGroupbysSourceExpr method) // so we need remove constant conjuncts when expr is not a leaf node. List<Expr> unassigned = getUnassignedConjuncts(node.getTblRefIds()); - if (!node.getChildren().isEmpty()) { + if (!node.getChildren().isEmpty() && !(node instanceof AggregationNode)) { unassigned = unassigned.stream() .filter(e -> !e.isConstant()).collect(Collectors.toList()); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java index cc64baeb34..361b5f38f5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/check/CheckCast.java @@ -59,11 +59,10 @@ public class CheckCast extends AbstractExpressionRewriteRule { /** * forbid this original and target type - * 1. boolean to date, datev2, datetime, datetimev2 - * 2. original type is object type - * 3. target type is object type - * 4. original type is same with target type - * 5. target type is null type + * 1. original type is object type + * 2. target type is object type + * 3. original type is same with target type + * 4. target type is null type */ private boolean checkPrimitiveType(DataType originalType, DataType targetType) { if (!originalType.isPrimitive() || !targetType.isPrimitive()) { @@ -72,9 +71,6 @@ public class CheckCast extends AbstractExpressionRewriteRule { if (originalType.equals(targetType)) { return false; } - if (originalType.isBooleanType() && targetType.isDateLikeType()) { - return false; - } if (originalType.isNullType()) { return true; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PruneOlapScanTablet.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PruneOlapScanTablet.java index 1cf718ff48..1b26f6b3f8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PruneOlapScanTablet.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PruneOlapScanTablet.java @@ -58,8 +58,11 @@ public class PruneOlapScanTablet extends OneRewriteRuleFactory { for (Long id : olapScan.getSelectedPartitionIds()) { Partition partition = table.getPartition(id); MaterializedIndex index = partition.getIndex(olapScan.getSelectedIndexId()); - selectedTabletIdsBuilder.addAll(getSelectedTabletIds(filter.getConjuncts(), - index, partition.getDistributionInfo())); + selectedTabletIdsBuilder + .addAll(getSelectedTabletIds(filter.getConjuncts(), index, + olapScan.getSelectedIndexId() == olapScan.getTable() + .getBaseIndexId(), + partition.getDistributionInfo())); } List<Long> selectedTabletIds = selectedTabletIdsBuilder.build(); if (new HashSet(selectedTabletIds).equals(new HashSet(olapScan.getSelectedTabletIds()))) { @@ -70,7 +73,7 @@ public class PruneOlapScanTablet extends OneRewriteRuleFactory { } private Collection<Long> getSelectedTabletIds(Set<Expression> expressions, - MaterializedIndex index, DistributionInfo info) { + MaterializedIndex index, boolean isBaseIndexSelected, DistributionInfo info) { if (info.getType() != DistributionInfoType.HASH) { return index.getTabletIdsInOrder(); } @@ -81,7 +84,8 @@ public class PruneOlapScanTablet extends OneRewriteRuleFactory { return new HashDistributionPruner(index.getTabletIdsInOrder(), hashInfo.getDistributionColumns(), filterMap, - hashInfo.getBucketNum() + hashInfo.getBucketNum(), + isBaseIndexSelected ).prune(); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/HashDistributionPruner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/HashDistributionPruner.java index 7314fe0564..2a60e4029a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/HashDistributionPruner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/HashDistributionPruner.java @@ -17,6 +17,7 @@ package org.apache.doris.planner; +import org.apache.doris.analysis.CreateMaterializedViewStmt; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.SlotRef; @@ -58,12 +59,15 @@ public class HashDistributionPruner implements DistributionPruner { private Map<String, PartitionColumnFilter> distributionColumnFilters; private int hashMod; + private boolean isBaseIndexSelected; + public HashDistributionPruner(List<Long> bucketsList, List<Column> columns, - Map<String, PartitionColumnFilter> filters, int hashMod) { + Map<String, PartitionColumnFilter> filters, int hashMod, boolean isBaseIndexSelected) { this.bucketsList = bucketsList; this.distributionColumns = columns; this.distributionColumnFilters = filters; this.hashMod = hashMod; + this.isBaseIndexSelected = isBaseIndexSelected; } // columnId: which column to compute @@ -75,7 +79,11 @@ public class HashDistributionPruner implements DistributionPruner { return Lists.newArrayList(bucketsList.get((int) ((hashValue & 0xffffffff) % hashMod))); } Column keyColumn = distributionColumns.get(columnId); - PartitionColumnFilter filter = distributionColumnFilters.get(keyColumn.getName()); + String columnName = isBaseIndexSelected ? keyColumn.getName() + : org.apache.doris.nereids.rules.rewrite.mv.AbstractSelectMaterializedIndexRule + .normalizeName( + CreateMaterializedViewStmt.mvColumnBuilder(keyColumn.getName())); + PartitionColumnFilter filter = distributionColumnFilters.get(columnName); if (null == filter) { // no filter in this column, no partition Key // return all subPartition diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java index b520e058e1..1fcac274ec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java @@ -692,7 +692,8 @@ public class OlapScanNode extends ScanNode { distributionPruner = new HashDistributionPruner(table.getTabletIdsInOrder(), info.getDistributionColumns(), columnFilters, - info.getBucketNum()); + info.getBucketNum(), + getSelectedIndexId() == olapTable.getBaseIndexId()); return distributionPruner.prune(); } case RANDOM: { diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/HashDistributionPrunerTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/HashDistributionPrunerTest.java index 7f3df304e3..2da47314d6 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/HashDistributionPrunerTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/HashDistributionPrunerTest.java @@ -91,7 +91,7 @@ public class HashDistributionPrunerTest { filters.put("channel", channelFilter); filters.put("shop_type", shopTypeFilter); - HashDistributionPruner pruner = new HashDistributionPruner(tabletIds, columns, filters, tabletIds.size()); + HashDistributionPruner pruner = new HashDistributionPruner(tabletIds, columns, filters, tabletIds.size(), true); Collection<Long> results = pruner.prune(); // 20 = 1 * 5 * 2 * 2 * 1 (element num of each filter) diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java index 22e6cd74f2..d8d7854355 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/OlapScanNodeTest.java @@ -69,7 +69,8 @@ public class OlapScanNodeTest { partitions, columns, filterMap, - 3); + 3, + true); Collection<Long> ids = partitionPruner.prune(); Assert.assertEquals(ids.size(), 1); @@ -112,7 +113,8 @@ public class OlapScanNodeTest { partitions, columns, filterMap, - 3); + 3, + true); Collection<Long> ids = partitionPruner.prune(); Assert.assertEquals(ids.size(), 3); diff --git a/regression-test/data/correctness_p0/test_constant_having.out b/regression-test/data/correctness_p0/test_constant_having.out new file mode 100644 index 0000000000..b0e2754c2a --- /dev/null +++ b/regression-test/data/correctness_p0/test_constant_having.out @@ -0,0 +1,5 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !sql1 -- + +-- !sql2 -- + diff --git a/regression-test/suites/correctness_p0/test_constant_having.groovy b/regression-test/suites/correctness_p0/test_constant_having.groovy new file mode 100644 index 0000000000..a21b4c0f74 --- /dev/null +++ b/regression-test/suites/correctness_p0/test_constant_having.groovy @@ -0,0 +1,74 @@ +// 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. + +suite("test_constant_having") { + sql """ + drop table if exists test_constant_having_t0; + """ + + sql """ + CREATE TABLE test_constant_having_t0(c0 VARCHAR(19) NOT NULL) DISTRIBUTED BY HASH (c0) PROPERTIES ("replication_num" = "1"); + """ + + sql """ + INSERT INTO test_constant_having_t0 (c0) VALUES (1),(2); + """ + + sql """ set enable_nereids_planner=false;""" + qt_sql1 """ + SELECT + CAST(DATE '1970-12-16' AS FLOAT), + 9998895.0, + 0.946221655 + FROM + test_constant_having_t0 + GROUP BY + test_constant_having_t0.c0 + HAVING + ( + NOT ( + CAST(false AS DATETIME) NOT IN (CAST(-994966193 AS DATETIME)) + ) + ) + ORDER BY + 1; + """ + + sql """ set enable_nereids_planner=true;""" + qt_sql2 """ + SELECT + CAST(DATE '1970-12-16' AS FLOAT), + 9998895.0, + 0.946221655 + FROM + test_constant_having_t0 + GROUP BY + test_constant_having_t0.c0 + HAVING + ( + NOT ( + CAST(false AS DATETIME) NOT IN (CAST(-994966193 AS DATETIME)) + ) + ) + ORDER BY + 1; + """ + + sql """ + drop table if exists test_constant_having_t0; + """ +} diff --git a/regression-test/suites/nereids_p0/datatype/test_cast.groovy b/regression-test/suites/nereids_p0/datatype/test_cast.groovy index f9b6ee6e35..29691297ef 100644 --- a/regression-test/suites/nereids_p0/datatype/test_cast.groovy +++ b/regression-test/suites/nereids_p0/datatype/test_cast.groovy @@ -74,4 +74,24 @@ suite("test_cast") { sql "select * from ${tbl} where case when k0 = 101 then 'true' else 1 end" result([[101]]) } + + test { + sql "select cast(false as datetime);" + result([[null]]) + } + + test { + sql "select cast(true as datetime);" + result([[null]]) + } + + test { + sql "select cast(false as date);" + result([[null]]) + } + + test { + sql "select cast(true as date);" + result([[null]]) + } } \ No newline at end of file diff --git a/regression-test/suites/nereids_p0/test_prune_tablet_mv.groovy b/regression-test/suites/nereids_p0/test_prune_tablet_mv.groovy new file mode 100644 index 0000000000..2a5c1349ac --- /dev/null +++ b/regression-test/suites/nereids_p0/test_prune_tablet_mv.groovy @@ -0,0 +1,45 @@ +// 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. + +suite("test_prune_tablet_mv") { + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + + sql "DROP TABLE IF EXISTS test_prune_tablet_t2" + sql """ + create table test_prune_tablet_t2(id int, c1 boolean) distributed by hash(id) BUCKETS 16 properties('replication_num'='1'); + """ + + createMV( """ + CREATE + MATERIALIZED VIEW mv_t2 AS + SELECT c1, + id + FROM test_prune_tablet_t2 + ORDER BY c1, + id; + """) + sql "insert into test_prune_tablet_t2 values(1,0),(2,0),(3,0),(4,0),(5,0),(6,0),(7,0);" + + explain { + sql("select * from test_prune_tablet_t2 where id = 3;") + contains "mv_t2" + contains "tablets=1/16" + } + + sql "DROP TABLE IF EXISTS test_prune_tablet_t2" +} \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org