From 4e8e97542394a492ff7c9c9facd37e69b443886d Mon Sep 17 00:00:00 2001 From: starocean999 <12095047@qq.com> Date: Sun, 3 Dec 2023 12:32:46 +0800 Subject: [PATCH] [fix](Nereids) should not push down project to the nullable side of outer join --- .../PushdownProjectThroughInnerOuterJoin.java | 4 +- ...hdownProjectThroughInnerOuterJoinTest.java | 53 +++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoin.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoin.java index 03fd3e8a8d8667..cf907e9578689a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoin.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoin.java @@ -136,8 +136,8 @@ private Plan pushdownProject(LogicalProject> p return null; } // we could not push nullable side project - if ((join.getJoinType().isLeftOuterJoin() && rightContains) - || (join.getJoinType().isRightOuterJoin() && leftContains)) { + if (((join.getJoinType().isLeftOuterJoin() || join.getJoinType().isFullOuterJoin()) && rightContains) + || ((join.getJoinType().isRightOuterJoin() || join.getJoinType().isFullOuterJoin()) && leftContains)) { return null; } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoinTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoinTest.java index 19be848332d4fa..5e539202d7a70e 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoinTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/exploration/join/PushdownProjectThroughInnerOuterJoinTest.java @@ -73,6 +73,59 @@ public void pushBothSide() { ); } + @Test + public void pushRightSide() { + // project (t1.id + 1) as alias, t1.name, (t2.id + 1) as alias, t2.name + List projectExprs = ImmutableList.of( + new Alias(new Add(scan1.getOutput().get(0), Literal.of(1)), "alias"), + scan1.getOutput().get(1), + scan2.getOutput().get(1) + ); + // complex projection contain ti.id, which isn't in Join Condition + LogicalPlan plan = new LogicalPlanBuilder(scan1) + .join(scan2, JoinType.LEFT_OUTER_JOIN, Pair.of(1, 1)) + .projectExprs(projectExprs) + .join(scan3, JoinType.INNER_JOIN, Pair.of(1, 1)) + .build(); + + PlanChecker.from(MemoTestUtils.createConnectContext(), plan) + .applyExploration(PushdownProjectThroughInnerOuterJoin.INSTANCE.buildRules()) + .printlnOrigin() + .printlnExploration() + .matchesExploration( + logicalJoin( + logicalProject( + logicalJoin( + logicalProject().when(project -> project.getProjects().size() == 2), + logicalOlapScan() + ) + ), + logicalOlapScan() + ) + ); + } + + @Test + public void pushNoSide() { + // project (t1.id + 1) as alias, t1.name, (t2.id + 1) as alias, t2.name + List projectExprs = ImmutableList.of( + new Alias(new Add(scan1.getOutput().get(0), Literal.of(1)), "alias"), + scan1.getOutput().get(1), + scan2.getOutput().get(1) + ); + // complex projection contain ti.id, which isn't in Join Condition + LogicalPlan plan = new LogicalPlanBuilder(scan1) + .join(scan2, JoinType.FULL_OUTER_JOIN, Pair.of(1, 1)) + .projectExprs(projectExprs) + .join(scan3, JoinType.INNER_JOIN, Pair.of(1, 1)) + .build(); + + int plansNumber = PlanChecker.from(MemoTestUtils.createConnectContext(), plan) + .applyExploration(PushdownProjectThroughInnerOuterJoin.INSTANCE.buildRules()) + .plansNumber(); + Assertions.assertEquals(1, plansNumber); + } + @Test public void pushdownProjectInCondition() { // project (t1.id + 1) as alias, t1.name, (t2.id + 1) as alias, t2.name