This is an automated email from the ASF dual-hosted git repository.

dataroaring pushed a commit to branch branch-3.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new 785fb1a0d85 branch-3.0: [fix](nereids) project child output to union 
output in correct order after eliminate empty relation #49257 (#49463)
785fb1a0d85 is described below

commit 785fb1a0d85129e20fb0449edd2983a544641cfe
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Mar 27 17:44:26 2025 +0800

    branch-3.0: [fix](nereids) project child output to union output in correct 
order after eliminate empty relation #49257 (#49463)
    
    Cherry-picked from #49257
    
    Co-authored-by: minghong <zhoumingh...@selectdb.com>
---
 .../rules/rewrite/EliminateEmptyRelation.java      |  22 ++-
 .../rules/rewrite/EliminateEmptyRelationTest.java  |  92 +++++++++++
 .../suites/empty_relation/eliminate_empty.groovy   | 173 +++++++++++++++++++++
 3 files changed, 279 insertions(+), 8 deletions(-)

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
index c45d55bb8ef..44c042687a9 100644
--- 
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
@@ -109,15 +109,21 @@ public class EliminateEmptyRelation implements 
RewriteRuleFactory {
                     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);
-                        }
+                        int childIdx = 
union.children().indexOf(nonEmptyChildren.get(0));
+                        if (childIdx >= 0) {
+                            List<SlotReference> childOutput = 
union.getRegularChildOutput(childIdx);
+                            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);
+                            }
 
-                        return new LogicalProject<>(projects, child);
+                            return new LogicalProject<>(projects, child);
+                        } else {
+                            // should not hit here.
+                            return null;
+                        }
                     }
                 }
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelationTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelationTest.java
new file mode 100644
index 00000000000..cf5752e63eb
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateEmptyRelationTest.java
@@ -0,0 +1,92 @@
+// 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.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.RelationId;
+import org.apache.doris.nereids.trees.plans.algebra.SetOperation.Qualifier;
+import org.apache.doris.nereids.trees.plans.logical.LogicalEmptyRelation;
+import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalUnion;
+import org.apache.doris.nereids.types.IntegerType;
+import org.apache.doris.nereids.types.StringType;
+import org.apache.doris.nereids.util.MemoPatternMatchSupported;
+import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.nereids.util.PlanChecker;
+import org.apache.doris.nereids.util.PlanConstructor;
+
+import com.google.common.collect.Lists;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link EliminateEmptyRelation}.
+ */
+class EliminateEmptyRelationTest implements MemoPatternMatchSupported {
+    private static final LogicalOlapScan scan1 = 
PlanConstructor.newLogicalOlapScan(0, "t1", 0);
+
+    @Test
+    void testEliminateUnionEmptyChild() {
+        List<SlotReference> emptyOutput = new ArrayList<>();
+        emptyOutput.add(new SlotReference("k", IntegerType.INSTANCE));
+        emptyOutput.add(new SlotReference("v", StringType.INSTANCE));
+        LogicalEmptyRelation emptyRelation = new LogicalEmptyRelation(new 
RelationId(1000), emptyOutput);
+
+        List<Plan> children = new ArrayList<>();
+        children.add(scan1);
+        children.add(emptyRelation);
+
+        List<Slot> scan1Output = scan1.getOutput();
+
+        List<NamedExpression> unionOutput = new ArrayList<>();
+        unionOutput.add(scan1Output.get(1));
+        unionOutput.add(scan1Output.get(0));
+
+        List<List<SlotReference>> regularOutput = new ArrayList<>();
+        regularOutput.add(Lists.newArrayList((SlotReference) 
scan1Output.get(1), (SlotReference) scan1Output.get(0)));
+        regularOutput.add(Lists.newArrayList(emptyOutput.get(1), 
emptyOutput.get(0)));
+
+        List<List<NamedExpression>> constantExprsList = new ArrayList<>();
+        LogicalPlan union = new LogicalUnion(Qualifier.ALL, unionOutput, 
regularOutput, constantExprsList,
+                false, children);
+
+        PlanChecker checker = 
PlanChecker.from(MemoTestUtils.createConnectContext(), union)
+                .applyTopDown(new EliminateEmptyRelation());
+        Plan plan = checker.getPlan();
+        System.out.println(plan.treeString());
+        /*
+         * LogicalProject[16] ( distinct=false, projects=[name#10003 AS 
`name`#10003, id#10002 AS `id`#10002] )
+         * +--LogicalOlapScan ( qualified=db.t1, 
indexName=<index_not_selected>, selectedIndexId=-1, preAgg=UNSET, 
operativeCol=[] )
+         */
+        //make sure project matches output column to the correct child output 
column
+        checker.matches(logicalProject().when(project -> {
+            NamedExpression name = project.getProjects().get(0);
+            Assertions.assertEquals("name", name.getName());
+            Assertions.assertInstanceOf(SlotReference.class, name.child(0));
+            Assertions.assertEquals("name", name.child(0).getExpressionName());
+            return true;
+        }));
+    }
+}
diff --git a/regression-test/suites/empty_relation/eliminate_empty.groovy 
b/regression-test/suites/empty_relation/eliminate_empty.groovy
index afe0a1ce487..13893c4976e 100644
--- a/regression-test/suites/empty_relation/eliminate_empty.groovy
+++ b/regression-test/suites/empty_relation/eliminate_empty.groovy
@@ -320,4 +320,177 @@ suite("eliminate_empty") {
         sql """drop table if exists table_5_undef_partitions2_keys3"""
         sql """drop table if exists table_10_undef_partitions2_keys3"""
     }
+
+    // union(A, empty) => A
+    sql """
+        set disable_nereids_rules='';
+        drop table  if exists dwd_bill_fact_bill_standard_info;
+        drop table  if exists ods_bill_fact_bill_jingdong_coupon;
+        CREATE TABLE `dwd_bill_fact_bill_standard_info` (
+        `tenant_id` bigint NULL,
+        `event_day` date NULL,
+        `platform` varchar(60) NULL,
+        `trade_order_no` varchar(192) NULL,
+        `bill_order_no` varchar(150) NULL,
+        `item_type` varchar(256) NULL,
+        `fa_type` varchar(384) NULL,
+        `id` bigint NULL,
+        `bill_name` varchar(150) NULL,
+        `bill_platform` varchar(60) NULL,
+        `sub_bill_platform` varchar(20) NULL COMMENT '平台子类型 ',
+        `account_no` varchar(150) NULL,
+        `shop_id` bigint NULL,
+        `shop_name` varchar(150) NULL,
+        `business_year` int NULL,
+        `business_mouth` int NULL,
+        `import_date` datetime NULL,
+        `input_method` varchar(60) NULL,
+        `import_code` bigint NULL,
+        `import_name` varchar(60) NULL,
+        `original_order_no` varchar(150) NULL,
+        `refund_order_no` varchar(50) NULL COMMENT '退款单号 ',
+        `bill_type` varchar(60) NULL,
+        `fa_order_no` varchar(120) NULL,
+        `sub_fa_type` text NULL,
+        `time_of_expense` datetime NULL,
+        `refund_time` datetime NULL COMMENT '退款时间 ',
+        `fa_settlement_time` datetime NULL,
+        `goods_name` varchar(765) NULL,
+        `opt_pay_account` varchar(150) NULL,
+        `account_name` varchar(150) NULL,
+        `actual_amount` decimal(19,4) NULL,
+        `income_out_direction` tinyint NULL,
+        `balance` decimal(19,4) NULL,
+        `amount_unit` varchar(30) NULL,
+        `amount_field_name` varchar(128) NULL COMMENT '金额字段名称 ',
+        `currency_id` int NULL,
+        `currency` varchar(30) NULL,
+        `business_channel` varchar(120) NULL,
+        `document_type` varchar(30) NULL,
+        `remark` varchar(765) NULL,
+        `abstracts` varchar(765) NULL,
+        `sub_order_no` varchar(150) NULL,
+        `seq` tinyint NULL,
+        `original_id` bigint NULL,
+        `original_goods_id` bigint NULL,
+        `plat_spec_id` bigint NULL COMMENT '平台规格ID ',
+        `create_time` datetime NULL,
+        `update_time` datetime NULL,
+        `creator_id` bigint NULL,
+        `updater_id` bigint NULL,
+        `version_no` bigint NULL,
+        `is_delete_doris` tinyint NULL COMMENT 'doris删除标记'
+        ) ENGINE=OLAP
+        UNIQUE KEY(`tenant_id`, `event_day`, `platform`, `trade_order_no`, 
`bill_order_no`, `item_type`, `fa_type`)
+        DISTRIBUTED BY HASH(`platform`) BUCKETS 1
+        properties("replication_num" = "1");
+
+        CREATE TABLE `ods_bill_fact_bill_jingdong_coupon` (
+        `tenant_id` bigint NOT NULL COMMENT '商户号',
+        `event_day` date NOT NULL COMMENT '分区',
+        `shop_id` bigint NOT NULL COMMENT '商店id',
+        `bill_coupon_id` varchar(150) NOT NULL COMMENT '生成优惠券号',
+        `coupon_name` varchar(765) NULL COMMENT '优惠券名称',
+        `shop_name` varchar(765) NULL COMMENT '店铺名称',
+        `effect_date` varchar(150) NULL COMMENT '作用日期',
+        `coupon_type` varchar(150) NULL COMMENT '优惠券类型',
+        `coupon_batch_code` varchar(150) NULL,
+        `coupon_code` varchar(150) NULL COMMENT '优惠券码',
+        `sku_id` varchar(150) NULL,
+        `money` decimal(19,4) NULL COMMENT '优惠券金额',
+        `contribute_party` varchar(150) NULL COMMENT '承担方',
+        `occur_time` datetime NULL,
+        `billing_time` datetime NULL,
+        `fee_settlement_time` datetime NULL,
+        `fa_settlement_time` datetime NULL COMMENT '业务日期',
+        `settlement_status` varchar(150) NULL COMMENT '结算状态',
+        `account_id` varchar(150) NULL COMMENT '账户id',
+        `account_no` varchar(150) NULL COMMENT '账号',
+        `trade_order_no` varchar(150) NULL COMMENT '商品编号',
+        `create_time` datetime NULL COMMENT '创建时间',
+        `update_time` datetime NULL COMMENT '修改时间',
+        `creator_id` bigint NULL COMMENT '创建人',
+        `updater_id` bigint NULL COMMENT '分区',
+        `currency_id` int NULL COMMENT '分区',
+        `version_no` bigint NULL COMMENT '分区',
+        `is_delete_doris` tinyint NULL COMMENT 'doris删除标记',
+        `summary_number` varchar(150) NULL
+        ) ENGINE=OLAP
+        UNIQUE KEY(`tenant_id`, `event_day`, `shop_id`, `bill_coupon_id`)
+        COMMENT 'OLAP'
+        DISTRIBUTED BY HASH(`shop_id`) BUCKETS 1
+        properties("replication_num" = "1");
+
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-10',-21911.4800);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-18',2592.5400);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-30',2218.4700);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-12',2940.4100);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-20',-25357.9600);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-24',-10754.1800);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-06',3089.6400);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-09',3066.7900);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-17',2271.7500);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-27',2290.4900);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-29',2363.7300);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-03',3664.7300);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-05',3014.6100);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-23',3175.2100);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-15',2622.6600);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-07',3444.7800);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-19',3348.2700);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-31',2003.6000);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-13',3981.9000);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-21',2850.0000);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-01',2543.0300);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-11',3671.9000);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-25',3303.3500);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-08',2510.0500);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-16',2869.5100);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-28',2405.4000);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-02',-65854.8900);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-04',3229.0900);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-14',1486.5400);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-22',3476.0100);
+        insert into 
dwd_bill_fact_bill_standard_info(tenant_id,shop_id,event_day,actual_amount) 
values(1548,102,'2025-01-26',2745.2200);
+        set parallel_pipeline_task_num=1;
+        """
+
+        sql """
+        SELECT
+            sum(s.actual_amount) sum_amount,
+            sum(cnt) sum_no
+        FROM
+            (
+                SELECT
+                    tenant_id,
+                    shop_id,
+                    event_day,
+                    sum(actual_amount) actual_amount,
+                    count(*) cnt
+                FROM
+                    dwd_bill_fact_bill_standard_info
+                group by
+                    tenant_id,
+                    shop_id,
+                    event_day
+                union
+                all
+                select
+                    tenant_id,
+                    shop_id,
+                    event_day,
+                    sum(money) actual_amount,
+                    count(*) cnt
+                from
+                    ods_bill_fact_bill_jingdong_coupon
+                group by
+                    tenant_id,
+                    shop_id,
+                    event_day
+            ) s
+        group by
+            s.tenant_id,
+            s.event_day,
+            s.shop_id;
+        """
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to