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

Reply via email to