From 64696829d14e51e0781794fbb98f50df6cfe2921 Mon Sep 17 00:00:00 2001 From: morrySnow <101034200+morrySnow@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:55:37 +0800 Subject: [PATCH] [fix](Nereids) mark join should not eliminate join when child is empty (#29409) --- .../rules/rewrite/EliminateEmptyRelation.java | 20 +++---- .../data/empty_relation/eliminate_empty.out | 5 ++ .../empty_relation/eliminate_empty.groovy | 52 +++++++++++++++++++ 3 files changed, 65 insertions(+), 12 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 cadc623727..2c0f9116ca 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 @@ -52,14 +52,10 @@ public class EliminateEmptyRelation implements RewriteRuleFactory { // join->empty logicalJoin(any(), any()) .when(this::hasEmptyRelationChild) - .then(join -> { - if (canReplaceJoinByEmptyRelation(join)) { - return new LogicalEmptyRelation( - ConnectContext.get().getStatementContext().getNextRelationId(), - join.getOutput()); - } - return join; - }) + .when(this::canReplaceJoinByEmptyRelation) + .then(join -> new LogicalEmptyRelation( + ConnectContext.get().getStatementContext().getNextRelationId(), + join.getOutput())) .toRule(RuleType.ELIMINATE_JOIN_ON_EMPTYRELATION), logicalFilter(logicalEmptyRelation()) .then(filter -> new LogicalEmptyRelation( @@ -186,17 +182,17 @@ public class EliminateEmptyRelation implements RewriteRuleFactory { ); } - private boolean hasEmptyRelationChild(LogicalJoin join) { + 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 + private boolean canReplaceJoinByEmptyRelation(LogicalJoin join) { + return !join.isMarkJoin() && ((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); + || (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 index a9b6de276d..1732199a89 100644 --- a/regression-test/data/empty_relation/eliminate_empty.out +++ b/regression-test/data/empty_relation/eliminate_empty.out @@ -80,3 +80,8 @@ PhysicalResultSink --PhysicalProject ----PhysicalEmptyRelation +-- !join_with_empty_child -- +2 8 e v 3 +4 7 at 2 +9 3 q 0 + diff --git a/regression-test/suites/empty_relation/eliminate_empty.groovy b/regression-test/suites/empty_relation/eliminate_empty.groovy index 326fa69d37..0aaa2bad06 100644 --- a/regression-test/suites/empty_relation/eliminate_empty.groovy +++ b/regression-test/suites/empty_relation/eliminate_empty.groovy @@ -163,4 +163,56 @@ suite("eliminate_empty") { (select * from eliminate_partition_prune where k1=100) T group by k3; """ + + sql """drop table if exists table_5_undef_partitions2_keys3""" + sql """drop table if exists table_10_undef_partitions2_keys3""" + + try { + sql """ + create table table_5_undef_partitions2_keys3 ( + `col_int_undef_signed_null` int null , + `col_int_undef_signed_not_null` int not null , + `col_varchar_10__undef_signed_null` varchar(10) null , + `col_varchar_10__undef_signed_not_null` varchar(10) not null , + `pk` int + ) engine=olap + distributed by hash(pk) buckets 10 + properties('replication_num' = '1'); + """ + + sql """ + insert into table_5_undef_partitions2_keys3(pk,col_int_undef_signed_null,col_int_undef_signed_not_null,col_varchar_10__undef_signed_null,col_varchar_10__undef_signed_not_null) values (0,9,3,"",'q'),(1,null,5,null,"ok"),(2,4,7,"","at"),(3,2,8,'e','v'),(4,null,6,'l',"really"); + """ + + sql """ + create table table_10_undef_partitions2_keys3 ( + `col_int_undef_signed_null` int null , + `col_int_undef_signed_not_null` int not null , + `col_varchar_10__undef_signed_null` varchar(10) null , + `col_varchar_10__undef_signed_not_null` varchar(10) not null , + `pk` int + ) engine=olap + distributed by hash(pk) buckets 10 + properties('replication_num' = '1'); + """ + + sql """ + insert into table_10_undef_partitions2_keys3(pk,col_int_undef_signed_null,col_int_undef_signed_not_null,col_varchar_10__undef_signed_null,col_varchar_10__undef_signed_not_null) values (0,null,7,'k','s'),(1,1,2,"",'l'),(2,null,7,"","look"),(3,null,5,null,'g'),(4,null,6,null,'o'),(5,4,0,'j','c'),(6,0,5,null,"so"),(7,null,3,"","something"),(8,7,0,null,""),(9,5,8,"","but"); + """ + + order_qt_join_with_empty_child """ + SELECT * + FROM table_5_undef_partitions2_keys3 AS t1 + WHERE t1.`col_int_undef_signed_null` IS NOT NULL + OR t1.`pk` IN ( + SELECT `col_int_undef_signed_null` + FROM table_10_undef_partitions2_keys3 AS t2 + LIMIT 0 + ); + """ + + } finally { + sql """drop table if exists table_5_undef_partitions2_keys3""" + sql """drop table if exists table_10_undef_partitions2_keys3""" + } } \ No newline at end of file