This is an automated email from the ASF dual-hosted git repository. englefly 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 62b1a7bcf3 [tpcds](nereids) add rule to eliminate empty relation #22203 62b1a7bcf3 is described below commit 62b1a7bcf3d327136a0aaafc0f532b06a9b4d2c0 Author: minghong <engle...@gmail.com> AuthorDate: Fri Aug 4 12:49:53 2023 +0800 [tpcds](nereids) add rule to eliminate empty relation #22203 1. eliminate emptyrelation, 2. const fold after filter pushdown --- .../doris/nereids/jobs/executor/Rewriter.java | 8 +- .../org/apache/doris/nereids/rules/RuleType.java | 6 + .../nereids/rules/analysis/CheckAfterRewrite.java | 2 +- .../rules/rewrite/EliminateEmptyRelation.java | 193 +++++++++++++++++++++ .../data/empty_relation/eliminate_empty.out | 72 ++++++++ .../nereids_tpcds_shape_sf100_p0/shape/query11.out | 16 +- .../nereids_tpcds_shape_sf100_p0/shape/query23.out | 2 +- .../nereids_tpcds_shape_sf100_p0/shape/query4.out | 24 +-- .../nereids_tpcds_shape_sf100_p0/shape/query74.out | 16 +- .../suites/empty_relation/eliminate_empty.groovy | 130 ++++++++++++++ regression-test/suites/empty_relation/load.groovy | 68 ++++++++ regression-test/suites/nereids_p0/load.groovy | 3 +- 12 files changed, 501 insertions(+), 39 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java index 606d9746cf..f603feda35 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java @@ -49,6 +49,7 @@ import org.apache.doris.nereids.rules.rewrite.CountDistinctRewrite; import org.apache.doris.nereids.rules.rewrite.DeferMaterializeTopNResult; import org.apache.doris.nereids.rules.rewrite.EliminateAggregate; import org.apache.doris.nereids.rules.rewrite.EliminateDedupJoinCondition; +import org.apache.doris.nereids.rules.rewrite.EliminateEmptyRelation; import org.apache.doris.nereids.rules.rewrite.EliminateFilter; import org.apache.doris.nereids.rules.rewrite.EliminateGroupByConstant; import org.apache.doris.nereids.rules.rewrite.EliminateLimit; @@ -228,7 +229,8 @@ public class Rewriter extends AbstractBatchJobExecutor { bottomUp(RuleSet.PUSH_DOWN_FILTERS), // after eliminate outer join, we can move some filters to join.otherJoinConjuncts, // this can help to translate plan to backend - topDown(new PushFilterInsideJoin()) + topDown(new PushFilterInsideJoin()), + topDown(new ExpressionNormalization()) ), custom(RuleType.CHECK_DATA_TYPES, CheckDataTypes::new), @@ -307,6 +309,10 @@ public class Rewriter extends AbstractBatchJobExecutor { new CollectFilterAboveConsumer(), new CollectProjectAboveConsumer() ) + ), + + topic("eliminate empty relation", + bottomUp(new EliminateEmptyRelation()) ) ); 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 15dd9f37a9..e545f58ce1 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 @@ -107,6 +107,12 @@ public enum RuleType { ELIMINATE_GROUP_BY_CONSTANT(RuleTypeClass.REWRITE), ELIMINATE_ORDER_BY_CONSTANT(RuleTypeClass.REWRITE), ELIMINATE_HINT(RuleTypeClass.REWRITE), + ELIMINATE_JOIN_ON_EMPTYRELATION(RuleTypeClass.REWRITE), + ELIMINATE_FILTER_ON_EMPTYRELATION(RuleTypeClass.REWRITE), + ELIMINATE_AGG_ON_EMPTYRELATION(RuleTypeClass.REWRITE), + ELIMINATE_UNION_ON_EMPTYRELATION(RuleTypeClass.REWRITE), + ELIMINATE_INTERSECTION_ON_EMPTYRELATION(RuleTypeClass.REWRITE), + ELIMINATE_EXCEPT_ON_EMPTYRELATION(RuleTypeClass.REWRITE), INFER_PREDICATES(RuleTypeClass.REWRITE), INFER_AGG_NOT_NULL(RuleTypeClass.REWRITE), INFER_SET_OPERATOR_DISTINCT(RuleTypeClass.REWRITE), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAfterRewrite.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAfterRewrite.java index a30cdfcbdd..26bb35192a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAfterRewrite.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CheckAfterRewrite.java @@ -106,7 +106,7 @@ public class CheckAfterRewrite extends OneAnalysisRuleFactory { notFromChildren = removeValidSlotsNotFromChildren(notFromChildren, childrenOutput); if (!notFromChildren.isEmpty()) { throw new AnalysisException(String.format("Input slot(s) not in child's output: %s in plan: %s," - + " child output is: %s", + + " child output is: %s\n" + "plan tree:\n" + plan.treeString(), StringUtils.join(notFromChildren.stream() .map(ExpressionTrait::toString) .collect(Collectors.toSet()), ", "), plan, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java new file mode 100644 index 0000000000..514c5972fa --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelation.java @@ -0,0 +1,193 @@ +// 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.rewrite; + +import org.apache.doris.nereids.rules.Rule; +import org.apache.doris.nereids.rules.RuleType; +import org.apache.doris.nereids.trees.expressions.Alias; +import org.apache.doris.nereids.trees.expressions.ExprId; +import org.apache.doris.nereids.trees.expressions.NamedExpression; +import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.JoinType; +import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.algebra.EmptyRelation; +import org.apache.doris.nereids.trees.plans.algebra.SetOperation; +import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate; +import org.apache.doris.nereids.trees.plans.logical.LogicalEmptyRelation; +import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; +import org.apache.doris.nereids.trees.plans.logical.LogicalProject; +import org.apache.doris.qe.ConnectContext; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * try to eliminate sub plan tree which contains EmptyRelation + */ +public class EliminateEmptyRelation implements RewriteRuleFactory { + + @Override + public List<Rule> buildRules() { + return ImmutableList.of( + // join->empty + logicalJoin(any(), any()) + .when(this::hasEmptyRelationChild) + .then(join -> { + if (canReplaceJoinByEmptyRelation(join)) { + return new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + join.getOutput()); + } + return join; + }) + .toRule(RuleType.ELIMINATE_JOIN_ON_EMPTYRELATION), + logicalFilter(logicalEmptyRelation()) + .then(filter -> new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + filter.getOutput()) + ).toRule(RuleType.ELIMINATE_FILTER_ON_EMPTYRELATION), + logicalAggregate(logicalEmptyRelation()) + .when(agg -> !agg.getGroupByExpressions().isEmpty()) + .then(agg -> new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + agg.getOutput()) + ).toRule(RuleType.ELIMINATE_AGG_ON_EMPTYRELATION), + + // after BuildAggForUnion rule, union may have more than 2 children. + logicalUnion(multi()).then(union -> { + if (union.children().size() == 0) { + // example: select * from (select 1,2 union select 3, 4) T; + // the children size is 0. (1,2) and (3,4) are stored in union.constantExprsList + return null; + } + List<Plan> nonEmptyChildren = union.children().stream() + .filter(child -> !(child instanceof EmptyRelation)) + .collect(Collectors.toList()); + if (nonEmptyChildren.isEmpty()) { + if (union.getConstantExprsList().isEmpty()) { + return new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + union.getOutput()); + } else { + return union.withChildren(ImmutableList.of()); + } + } else if (nonEmptyChildren.size() == 1) { + if (union.getConstantExprsList().isEmpty()) { + Plan child = nonEmptyChildren.get(0); + List<Slot> unionOutput = union.getOutput(); + List<Slot> childOutput = child.getOutput(); + List<NamedExpression> projects = Lists.newArrayList(); + for (int i = 0; i < unionOutput.size(); i++) { + ExprId id = unionOutput.get(i).getExprId(); + Alias alias = new Alias(id, childOutput.get(i), unionOutput.get(i).getName()); + projects.add(alias); + } + + LogicalProject project = new LogicalProject<>(projects, child); + return project; + } + } + + if (union.children().size() != nonEmptyChildren.size()) { + return union.withChildren(ImmutableList.copyOf(nonEmptyChildren)); + } else { + // no empty relation child, do not change union + return null; + } + }).toRule(RuleType.ELIMINATE_UNION_ON_EMPTYRELATION), + // set intersect + logicalIntersect(multi()).then(intersect -> { + List<Plan> emptyChildren = intersect.children().stream() + .filter(EmptyRelation.class::isInstance) + .collect(Collectors.toList()); + if (emptyChildren.isEmpty()) { + // no empty relation child, plan not changed + return null; + } else { + // there is empty relation child, the intersection result is empty. + return new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + intersect.getOutput()); + } + }).toRule(RuleType.ELIMINATE_INTERSECTION_ON_EMPTYRELATION), + // set except + logicalExcept(multi()).then(except -> { + Plan first = except.child(0); + if (first instanceof EmptyRelation) { + // empty except any => empty + return new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + except.getOutput()); + } else { + List<Plan> nonEmptyChildren = except.children().stream() + .filter(child -> !(child instanceof EmptyRelation)) + .collect(Collectors.toList()); + if (nonEmptyChildren.size() == 1) { + // the first child is not empty, others are all empty + // case 1. FIRST except(distinct) empty = > project(AGG(FIRST)) + // case 2. FIRST except(all) empty = > project(FIRST) + Plan projectChild; + if (except.getQualifier() == SetOperation.Qualifier.DISTINCT) { + List<NamedExpression> firstOutputNamedExpressions = first.getOutput() + .stream().map(slot -> (NamedExpression) slot) + .collect(ImmutableList.toImmutableList()); + projectChild = new LogicalAggregate<>(ImmutableList.copyOf(firstOutputNamedExpressions), + firstOutputNamedExpressions, true, Optional.empty(), first); + } else { + projectChild = first; + } + + List<Slot> exceptOutput = except.getOutput(); + List<Slot> projectInputSlots = projectChild.getOutput(); + + List<NamedExpression> projects = Lists.newArrayList(); + for (int i = 0; i < exceptOutput.size(); i++) { + ExprId id = exceptOutput.get(i).getExprId(); + Alias alias = new Alias(id, projectInputSlots.get(i), exceptOutput.get(i).getName()); + projects.add(alias); + } + LogicalProject project = new LogicalProject(projects, projectChild); + return project; + } else if (nonEmptyChildren.size() == except.children().size()) { + return null; + } else { + return except.withChildren(nonEmptyChildren); + } + } + }).toRule(RuleType.ELIMINATE_EXCEPT_ON_EMPTYRELATION) + ); + } + + private boolean hasEmptyRelationChild(LogicalJoin join) { + return join.left() instanceof EmptyRelation || join.right() instanceof EmptyRelation; + } + + private boolean canReplaceJoinByEmptyRelation(LogicalJoin join) { + return (join.getJoinType() == JoinType.INNER_JOIN + || join.getJoinType() == JoinType.LEFT_SEMI_JOIN + || join.getJoinType() == JoinType.RIGHT_SEMI_JOIN + || join.getJoinType() == JoinType.CROSS_JOIN) + || (join.getJoinType() == JoinType.LEFT_OUTER_JOIN && join.left() instanceof EmptyRelation) + || (join.getJoinType() == JoinType.RIGHT_OUTER_JOIN && join.right() instanceof EmptyRelation); + } + +} diff --git a/regression-test/data/empty_relation/eliminate_empty.out b/regression-test/data/empty_relation/eliminate_empty.out new file mode 100644 index 0000000000..e864cd46e3 --- /dev/null +++ b/regression-test/data/empty_relation/eliminate_empty.out @@ -0,0 +1,72 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !onerow_union -- +1 2 +3 4 + +-- !join -- +PhysicalResultSink +--PhysicalEmptyRelation + +-- !explain_union_empty_data -- +PhysicalResultSink +--PhysicalDistribute +----hashAgg[LOCAL] +------PhysicalProject +--------PhysicalOlapScan[nation] + +-- !union_empty_data -- +1 + +-- !explain_union_empty_empty -- +PhysicalResultSink +--PhysicalEmptyRelation + +-- !union_empty_empty -- + +-- !union_emtpy_onerow -- +10 + +-- !explain_intersect_data_empty -- +PhysicalResultSink +--PhysicalEmptyRelation + +-- !explain_intersect_empty_data -- +PhysicalResultSink +--PhysicalEmptyRelation + +-- !explain_except_data_empty -- +PhysicalResultSink +--PhysicalDistribute +----PhysicalProject +------hashAgg[LOCAL] +--------PhysicalProject +----------PhysicalOlapScan[nation] + +-- !explain_except_data_empty_data -- +PhysicalResultSink +--PhysicalDistribute +----PhysicalExcept +------PhysicalDistribute +--------PhysicalProject +----------PhysicalOlapScan[nation] +------PhysicalDistribute +--------PhysicalProject +----------filter(( not (n_nationkey = 1))) +------------PhysicalOlapScan[nation] + +-- !except_data_empty_data -- +1 + +-- !explain_except_empty_data -- +PhysicalResultSink +--PhysicalEmptyRelation + +-- !intersect_data_empty -- + +-- !intersect_empty_data -- + +-- !except_data_empty -- +1 + +-- !except_empty_data -- + diff --git a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query11.out b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query11.out index 4fa9d8a329..11be7dc5e2 100644 --- a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query11.out +++ b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query11.out @@ -12,16 +12,14 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) ------------------PhysicalDistribute --------------------hashJoin[INNER_JOIN](store_sales.ss_sold_date_sk = date_dim.d_date_sk) ----------------------PhysicalProject -------------------------filter('s' IN ('s', 'w')) ---------------------------PhysicalOlapScan[store_sales] +------------------------PhysicalOlapScan[store_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('s' IN ('s', 'w')d_year IN (2001, 2002)) +--------------------------filter(d_year IN (2001, 2002)) ----------------------------PhysicalOlapScan[date_dim] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter('s' IN ('s', 'w')) -------------------------PhysicalOlapScan[customer] +----------------------PhysicalOlapScan[customer] ------PhysicalProject --------hashAgg[GLOBAL] ----------PhysicalDistribute @@ -31,16 +29,14 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) ------------------PhysicalDistribute --------------------hashJoin[INNER_JOIN](web_sales.ws_sold_date_sk = date_dim.d_date_sk) ----------------------PhysicalProject -------------------------filter('w' IN ('s', 'w')) ---------------------------PhysicalOlapScan[web_sales] +------------------------PhysicalOlapScan[web_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter(d_year IN (2001, 2002)'w' IN ('s', 'w')) +--------------------------filter(d_year IN (2001, 2002)) ----------------------------PhysicalOlapScan[date_dim] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter('w' IN ('s', 'w')) -------------------------PhysicalOlapScan[customer] +----------------------PhysicalOlapScan[customer] --PhysicalResultSink ----PhysicalTopN ------PhysicalDistribute diff --git a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query23.out b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query23.out index b9f1e7b6f8..871dcbc979 100644 --- a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query23.out +++ b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query23.out @@ -22,7 +22,7 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) --PhysicalCteAnchor ( cteId=CTEId#2 ) ----PhysicalCteProducer ( cteId=CTEId#2 ) ------PhysicalProject ---------NestedLoopJoin[INNER_JOIN](cast(ssales as DOUBLE) > cast(((cast(95 as DECIMALV3(8, 5)) / 100.0) * tpcds_cmax) as DOUBLE)) +--------NestedLoopJoin[INNER_JOIN](cast(ssales as DOUBLE) > cast((0.9500 * tpcds_cmax) as DOUBLE)) ----------hashAgg[LOCAL] ------------PhysicalProject --------------hashJoin[INNER_JOIN](store_sales.ss_customer_sk = customer.c_customer_sk) diff --git a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query4.out b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query4.out index 3e1360aafe..fd7817615f 100644 --- a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query4.out +++ b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query4.out @@ -13,15 +13,13 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) --------------------hashJoin[INNER_JOIN](customer.c_customer_sk = store_sales.ss_customer_sk) ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('s' IN ('c', 's', 'w')) -----------------------------PhysicalOlapScan[store_sales] +--------------------------PhysicalOlapScan[store_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('s' IN ('c', 's', 'w')) -----------------------------PhysicalOlapScan[customer] +--------------------------PhysicalOlapScan[customer] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter(d_year IN (2000, 1999)'s' IN ('c', 's', 'w')) +----------------------filter(d_year IN (2000, 1999)) ------------------------PhysicalOlapScan[date_dim] ------PhysicalProject --------hashAgg[GLOBAL] @@ -33,15 +31,13 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) --------------------hashJoin[INNER_JOIN](customer.c_customer_sk = catalog_sales.cs_bill_customer_sk) ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('c' IN ('c', 's', 'w')) -----------------------------PhysicalOlapScan[catalog_sales] +--------------------------PhysicalOlapScan[catalog_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('c' IN ('c', 's', 'w')) -----------------------------PhysicalOlapScan[customer] +--------------------------PhysicalOlapScan[customer] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter('c' IN ('c', 's', 'w')d_year IN (2000, 1999)) +----------------------filter(d_year IN (2000, 1999)) ------------------------PhysicalOlapScan[date_dim] ------PhysicalProject --------hashAgg[GLOBAL] @@ -53,15 +49,13 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) --------------------hashJoin[INNER_JOIN](customer.c_customer_sk = web_sales.ws_bill_customer_sk) ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('w' IN ('c', 's', 'w')) -----------------------------PhysicalOlapScan[web_sales] +--------------------------PhysicalOlapScan[web_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('w' IN ('c', 's', 'w')) -----------------------------PhysicalOlapScan[customer] +--------------------------PhysicalOlapScan[customer] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter('w' IN ('c', 's', 'w')d_year IN (2000, 1999)) +----------------------filter(d_year IN (2000, 1999)) ------------------------PhysicalOlapScan[date_dim] --PhysicalResultSink ----PhysicalTopN diff --git a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query74.out b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query74.out index 25b48b8fda..9cd4ce4905 100644 --- a/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query74.out +++ b/regression-test/data/nereids_tpcds_shape_sf100_p0/shape/query74.out @@ -12,16 +12,14 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) ------------------PhysicalDistribute --------------------hashJoin[INNER_JOIN](store_sales.ss_sold_date_sk = date_dim.d_date_sk) ----------------------PhysicalProject -------------------------filter('s' IN ('s', 'w')) ---------------------------PhysicalOlapScan[store_sales] +------------------------PhysicalOlapScan[store_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter('s' IN ('s', 'w')d_year IN (2000, 1999)) +--------------------------filter(d_year IN (2000, 1999)) ----------------------------PhysicalOlapScan[date_dim] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter('s' IN ('s', 'w')) -------------------------PhysicalOlapScan[customer] +----------------------PhysicalOlapScan[customer] ------PhysicalProject --------hashAgg[GLOBAL] ----------PhysicalDistribute @@ -31,16 +29,14 @@ PhysicalCteAnchor ( cteId=CTEId#0 ) ------------------PhysicalDistribute --------------------hashJoin[INNER_JOIN](web_sales.ws_sold_date_sk = date_dim.d_date_sk) ----------------------PhysicalProject -------------------------filter('w' IN ('s', 'w')) ---------------------------PhysicalOlapScan[web_sales] +------------------------PhysicalOlapScan[web_sales] ----------------------PhysicalDistribute ------------------------PhysicalProject ---------------------------filter(d_year IN (2000, 1999)'w' IN ('s', 'w')) +--------------------------filter(d_year IN (2000, 1999)) ----------------------------PhysicalOlapScan[date_dim] ------------------PhysicalDistribute --------------------PhysicalProject -----------------------filter('w' IN ('s', 'w')) -------------------------PhysicalOlapScan[customer] +----------------------PhysicalOlapScan[customer] --PhysicalResultSink ----PhysicalTopN ------PhysicalDistribute diff --git a/regression-test/suites/empty_relation/eliminate_empty.groovy b/regression-test/suites/empty_relation/eliminate_empty.groovy new file mode 100644 index 0000000000..d9050e9cdc --- /dev/null +++ b/regression-test/suites/empty_relation/eliminate_empty.groovy @@ -0,0 +1,130 @@ +/* + * 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("eliminate_empty") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql 'set enable_nereids_planner=true' + sql 'set enable_fallback_to_original_planner=false' + sql 'set forbid_unknown_col_stats=false' + qt_onerow_union """ + select * from (select 1, 2 union select 3, 4) T + """ + + qt_join """ + explain shape plan + select * + from + nation + join + (select * from region where false) R + """ + + qt_explain_union_empty_data """ + explain shape plan + select * + from (select n_nationkey from nation union select r_regionkey from region where false) T + """ + qt_union_empty_data """ + select * + from (select n_nationkey from nation union select r_regionkey from region where false) T + """ + + qt_explain_union_empty_empty """ + explain shape plan + select * + from ( + select n_nationkey from nation where false + union + select r_regionkey from region where false + ) T + """ + qt_union_empty_empty """ + select * + from ( + select n_nationkey from nation where false + union + select r_regionkey from region where false + ) T + """ + qt_union_emtpy_onerow """ + select * + from ( + select n_nationkey from nation where false + union + select 10 + union + select 10 + )T + """ + + qt_explain_intersect_data_empty """ + explain shape plan + select n_nationkey from nation intersect select r_regionkey from region where false + """ + + qt_explain_intersect_empty_data """ + explain shape plan + select r_regionkey from region where false intersect select n_nationkey from nation + """ + + qt_explain_except_data_empty """ + explain shape plan + select n_nationkey from nation except select r_regionkey from region where false + """ + + qt_explain_except_data_empty_data """ + explain shape plan + select n_nationkey from nation + except + select r_regionkey from region where false + except + select n_nationkey from nation where n_nationkey != 1; + """ + + qt_except_data_empty_data """ + select n_nationkey from nation + except + select r_regionkey from region where false + except + select n_nationkey from nation where n_nationkey != 1; + """ + + qt_explain_except_empty_data """ + explain shape plan + select r_regionkey from region where false except select n_nationkey from nation + """ + + + qt_intersect_data_empty """ + select n_nationkey from nation intersect select r_regionkey from region where false + """ + + qt_intersect_empty_data """ + select r_regionkey from region where false intersect select n_nationkey from nation + """ + + qt_except_data_empty """ + select n_nationkey from nation except select r_regionkey from region where false + """ + + qt_except_empty_data """ + select r_regionkey from region where false except select n_nationkey from nation + """ +} \ No newline at end of file diff --git a/regression-test/suites/empty_relation/load.groovy b/regression-test/suites/empty_relation/load.groovy new file mode 100644 index 0000000000..98adb6f012 --- /dev/null +++ b/regression-test/suites/empty_relation/load.groovy @@ -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. + +suite("load") { + String database = context.config.getDbNameByFile(context.file) + sql "drop database if exists ${database}" + sql "create database ${database}" + sql "use ${database}" + sql """ + drop table if exists lineitem; + """ + sql ''' + drop table if exists nation; + ''' + + sql ''' + CREATE TABLE `nation` ( + `n_nationkey` int(11) NOT NULL, + `n_name` varchar(25) NOT NULL, + `n_regionkey` int(11) NOT NULL + ) ENGINE=OLAP + DUPLICATE KEY(`N_NATIONKEY`) + COMMENT "OLAP" + DISTRIBUTED BY HASH(`N_NATIONKEY`) BUCKETS 1 + PROPERTIES ( + "replication_num" = "1" + ); + ''' + + sql ''' + insert into nation values (1, "china", 2), (1, "china", 2); + ''' + + sql ''' + drop table if exists region; + ''' + + sql ''' + CREATE TABLE region ( + r_regionkey int NOT NULL, + r_name VARCHAR(25) NOT NULL + )ENGINE=OLAP + DUPLICATE KEY(`r_regionkey`) + COMMENT "OLAP" + DISTRIBUTED BY HASH(`r_regionkey`) BUCKETS 1 + PROPERTIES ( + "replication_num" = "1" + ); + ''' + + sql ''' + insert into region values (2, "asia") + ''' +} \ No newline at end of file diff --git a/regression-test/suites/nereids_p0/load.groovy b/regression-test/suites/nereids_p0/load.groovy index 8c02918667..158c3d72ab 100644 --- a/regression-test/suites/nereids_p0/load.groovy +++ b/regression-test/suites/nereids_p0/load.groovy @@ -15,8 +15,9 @@ // specific language governing permissions and limitations // under the License. -suite("load_nereids_test_query_db") { +suite("load") { sql "SET enable_nereids_planner=true" + sql "set forbid_unknown_col_stats=false" sql "SET enable_fallback_to_original_planner=false" // init query case data def dbName = "nereids_test_query_db" --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org