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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]