This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push:
new ec25f7573e7 branch-2.1: [fix](nereids) project child output to union
output in correct order after eliminate empty relation #49257 (#49464)
ec25f7573e7 is described below
commit ec25f7573e70a7bb03830a1c7c5b7aaa0474ea7d
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Mar 29 20:33:42 2025 +0800
branch-2.1: [fix](nereids) project child output to union output in correct
order after eliminate empty relation #49257 (#49464)
Cherry-picked from #49257
Co-authored-by: minghong <[email protected]>
---
.../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 af3ec156e08..31f314de9b3 100644
--- a/regression-test/suites/empty_relation/eliminate_empty.groovy
+++ b/regression-test/suites/empty_relation/eliminate_empty.groovy
@@ -319,4 +319,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: [email protected]
For additional commands, e-mail: [email protected]