diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/JoinSplitForNullSkewTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/JoinSplitForNullSkewTest.java index 51ad3981867ed88..3f747f090a9e0f4 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/JoinSplitForNullSkewTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/JoinSplitForNullSkewTest.java @@ -1,3 +1,20 @@ +// 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.RuleType; @@ -17,13 +34,14 @@ import java.util.Set; -public class JoinSplitForNullSkewTest extends TestWithFeService implements MemoPatternMatchSupported { +public class JoinSplitForNullSkewTest extends TestWithFeService implements MemoPatternMatchSupported { private static final MockUp mockUpForSubClass = new MockUp() { @Mock public Set getEnableNereidsRules() { return ImmutableSet.of(RuleType.valueOf("JOIN_SPLIT_FOR_NULL_SKEW").type()); } }; + @Override protected void runBeforeAll() throws Exception { createDatabase("test"); @@ -41,8 +59,8 @@ void testRewriteLeftJoin() { .analyze("select t1.a,t1.b,t2.c,t2.dt from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a=t2.a order by 1,2,3,4") .rewrite() .printlnTree() - .matches(logicalUnion(logicalProject(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof IsNull)) - , logicalProject(logicalJoin(logicalProject(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof Not)),any())))); + .matches(logicalUnion(logicalProject(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof IsNull)), + logicalProject(logicalJoin(logicalProject(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof Not)), any())))); } @Test @@ -51,8 +69,8 @@ void testRewriteLeftJoinSelectAll() { .analyze("select * from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a=t2.a order by 1,2,3,4") .rewrite() .printlnTree() - .matches(logicalUnion(logicalProject(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof IsNull)) - , logicalProject(logicalJoin(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof Not), any())))); + .matches(logicalUnion(logicalProject(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof IsNull)), + logicalProject(logicalJoin(logicalFilter(any()).when(f -> f.getConjuncts().size() == 1 && f.getConjuncts().iterator().next() instanceof Not), any())))); } @Test @@ -62,41 +80,40 @@ void testRewriteRightJoinSelectAll() { .rewrite() .printlnTree() .matches(logicalUnion(logicalProject(logicalFilter(any()).when(f -> { - if (f.getConjuncts().size() != 1) { - return false; - } - Expression firstConjunct = f.getConjuncts().iterator().next(); - if (!(firstConjunct instanceof IsNull)) { - return false; - } - if (!(firstConjunct.child(0) instanceof SlotReference)) { - return false; - } - if (!((SlotReference) firstConjunct.child(0)).getQualifiedName().equals("internal.test.t2.c")) { - return false; - } - return true; - })) - , logicalProject(logicalJoin(logicalProject(logicalFilter(any()).when(f -> { - if (f.getConjuncts().size() != 1) { - return false; - } - Expression firstConjunct = f.getConjuncts().iterator().next(); - if (!(firstConjunct instanceof Not) || !(firstConjunct.child(0) instanceof IsNull)) { - return false; - } - Expression expr = firstConjunct.child(0).child(0); - if (!(expr instanceof SlotReference)) { - return false; - } - if (!((SlotReference) expr).getQualifiedName().equals("internal.test.t2.c")) { - return false; - } - return true; - })), any())))); + if (f.getConjuncts().size() != 1) { + return false; + } + Expression firstConjunct = f.getConjuncts().iterator().next(); + if (!(firstConjunct instanceof IsNull)) { + return false; + } + if (!(firstConjunct.child(0) instanceof SlotReference)) { + return false; + } + if (!((SlotReference) firstConjunct.child(0)).getQualifiedName().equals("internal.test.t2.c")) { + return false; + } + return true; + })), + logicalProject(logicalJoin(logicalProject(logicalFilter(any()).when(f -> { + if (f.getConjuncts().size() != 1) { + return false; + } + Expression firstConjunct = f.getConjuncts().iterator().next(); + if (!(firstConjunct instanceof Not) || !(firstConjunct.child(0) instanceof IsNull)) { + return false; + } + Expression expr = firstConjunct.child(0).child(0); + if (!(expr instanceof SlotReference)) { + return false; + } + if (!((SlotReference) expr).getQualifiedName().equals("internal.test.t2.c")) { + return false; + } + return true; + })), any())))); } - @Test void testRewriteWhenLeftChildHasIsNotNullFilter() { PlanChecker.from(connectContext) diff --git a/regression-test/data/nereids_rules_p0/split_join_for_null_skew/split_join_for_null_skew.out b/regression-test/data/nereids_rules_p0/split_join_for_null_skew/split_join_for_null_skew.out new file mode 100644 index 000000000000000..0001ea54bfe6837 --- /dev/null +++ b/regression-test/data/nereids_rules_p0/split_join_for_null_skew/split_join_for_null_skew.out @@ -0,0 +1,153 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !int -- +\N 103 \N \N +\N 107 \N \N +1 100 apple 2023-01-01T10:00 +1 100 apple 2023-01-01T10:00 +1 100 apple 2023-01-01T10:00 +1 100 apple 2023-01-01T10:00 +2 101 banana 2023-01-02T11:00 +3 102 cherry 2023-01-03T12:00 +3 102 cherry 2023-01-03T12:00 +3 102 cherry 2023-01-03T12:00 +3 102 cherry 2023-01-03T12:00 +4 104 elderberry 2023-01-05T14:00 +5 105 \N 2023-01-06T15:00 +5 105 \N 2023-01-06T15:00 +5 105 \N 2023-01-06T15:00 +5 105 \N 2023-01-06T15:00 +6 106 fig 2023-01-07T16:00 + +-- !on_condition_has_plus_expr -- +\N 103 \N \N +\N 107 \N \N +1 100 2 101 +1 100 2 101 +2 101 3 102 +2 101 3 102 +3 102 4 104 +3 102 4 104 +4 104 5 105 +4 104 5 105 +5 105 6 106 +5 105 6 106 +6 106 \N \N + +-- !on_condition_has_abs_expr -- +\N 103 \N \N +\N 107 \N \N +1 100 1 100 +1 100 1 100 +1 100 1 100 +1 100 1 100 +2 101 2 101 +3 102 3 102 +3 102 3 102 +3 102 3 102 +3 102 3 102 +4 104 4 104 +5 105 5 105 +5 105 5 105 +5 105 5 105 +5 105 5 105 +6 106 6 106 + +-- !varchar -- +\N 103 2023-01-04T13:00 date +\N 107 2023-01-08T17:00 grape +1 100 2023-01-01T10:00 apple +1 100 2023-01-01T10:00 apple +1 100 2023-01-01T10:00 apple +1 100 2023-01-01T10:00 apple +2 101 2023-01-02T11:00 banana +3 102 2023-01-03T12:00 cherry +3 102 2023-01-03T12:00 cherry +3 102 2023-01-03T12:00 cherry +3 102 2023-01-03T12:00 cherry +4 104 2023-01-05T14:00 elderberry +5 105 \N \N +5 105 \N \N +6 106 2023-01-07T16:00 fig + +-- !datetime -- +100 100 1 apple +100 100 1 apple +100 100 1 apple +100 100 1 apple +101 101 2 banana +102 102 3 cherry +102 102 3 cherry +102 102 3 cherry +102 102 3 cherry +103 103 \N date +104 104 4 elderberry +105 105 5 \N +105 105 5 \N +105 105 5 \N +105 105 5 \N +106 106 6 fig +107 107 \N grape + +-- !int_has_filter -- +1 100 2023-01-01T10:00 100 +1 100 2023-01-01T10:00 100 +1 100 2023-01-01T10:00 100 +1 100 2023-01-01T10:00 100 + +-- !int_has_is_not_null -- +2023-01-01T10:00 100 1 100 +2023-01-01T10:00 100 1 100 +2023-01-01T10:00 100 1 100 +2023-01-01T10:00 100 1 100 +2023-01-02T11:00 101 2 101 +2023-01-03T12:00 102 3 102 +2023-01-03T12:00 102 3 102 +2023-01-03T12:00 102 3 102 +2023-01-03T12:00 102 3 102 +2023-01-05T14:00 104 4 104 +2023-01-06T15:00 105 5 105 +2023-01-06T15:00 105 5 105 +2023-01-06T15:00 105 5 105 +2023-01-06T15:00 105 5 105 +2023-01-07T16:00 106 6 106 + +-- !int_has_is_null -- +2023-01-04T13:00 103 \N \N +2023-01-08T17:00 107 \N \N + +-- !varchar -- +\N \N 2023-01-06T15:00 \N +\N \N 2023-01-06T15:00 \N +\N 103 2023-01-04T13:00 date +\N 107 2023-01-08T17:00 grape +1 100 2023-01-01T10:00 apple +1 100 2023-01-01T10:00 apple +1 100 2023-01-01T10:00 apple +1 100 2023-01-01T10:00 apple +2 101 2023-01-02T11:00 banana +3 102 2023-01-03T12:00 cherry +3 102 2023-01-03T12:00 cherry +3 102 2023-01-03T12:00 cherry +3 102 2023-01-03T12:00 cherry +4 104 2023-01-05T14:00 elderberry +6 106 2023-01-07T16:00 fig + +-- !datetime -- +100 100 1 apple +100 100 1 apple +100 100 1 apple +100 100 1 apple +101 101 2 banana +102 102 3 cherry +102 102 3 cherry +102 102 3 cherry +102 102 3 cherry +103 103 \N date +104 104 4 elderberry +105 105 5 \N +105 105 5 \N +105 105 5 \N +105 105 5 \N +106 106 6 fig +107 107 \N grape + diff --git a/regression-test/suites/nereids_rules_p0/split_join_for_null_skew/split_join_for_null_skew.groovy b/regression-test/suites/nereids_rules_p0/split_join_for_null_skew/split_join_for_null_skew.groovy new file mode 100644 index 000000000000000..1b7a24308a45f53 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/split_join_for_null_skew/split_join_for_null_skew.groovy @@ -0,0 +1,55 @@ +// 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("split_join_for_null_skew") { + sql "set enable_nereids_rules = 'JOIN_SPLIT_FOR_NULL_SKEW'" + + sql "drop table if exists split_join_for_null_skew_t" + sql """create table split_join_for_null_skew_t(a int null, b int not null, c varchar(10) null, d date, dt datetime) + distributed by hash(a) properties("replication_num"="1"); + """ + sql """ + INSERT INTO split_join_for_null_skew_t (a, b, c, d, dt) VALUES + (1, 100, 'apple', '2023-01-01', '2023-01-01 10:00:00'), + (1, 100, 'apple', '2023-01-01', '2023-01-01 10:00:00'), + (2, 101, 'banana', '2023-01-02', '2023-01-02 11:00:00'), + (3, 102, 'cherry', '2023-01-03', '2023-01-03 12:00:00'), + (3, 102, 'cherry', '2023-01-03', '2023-01-03 12:00:00'), + (NULL, 103, 'date', '2023-01-04', '2023-01-04 13:00:00'), + (4, 104, 'elderberry', '2023-01-05', '2023-01-05 14:00:00'), + (5, 105, NULL, '2023-01-06', '2023-01-06 15:00:00'), + (5, 105, NULL, '2023-01-06', '2023-01-06 15:00:00'), + (6, 106, 'fig', '2023-01-07', '2023-01-07 16:00:00'), + (NULL, 107, 'grape', '2023-01-08', '2023-01-08 17:00:00'); + """ + // left join on slot + qt_int "select t1.a,t1.b,t2.c,t2.dt from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a=t2.a order by 1,2,3,4" + qt_on_condition_has_plus_expr "select t1.a,t1.b,t2.a,t2.b from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a+1=t2.a order by 1,2,3,4" + qt_on_condition_has_abs_expr "select t1.a,t1.b,t2.a,t2.b from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on abs(t1.a)=t2.a order by 1,2,3,4" + qt_varchar "select t1.a,t1.b,t2.dt,t2.c from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.c=t2.c order by 1,2,3,4" + qt_datetime "select t2.b,t1.b,t2.a,t2.c from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.dt=t2.dt order by 1,2,3,4" + + // left join child has filter + qt_int_has_filter "select t1.a,t1.b,t2.dt,t2.b from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a=t2.a where t1.a =1 order by 1,2,3,4" + qt_int_has_is_not_null "select t1.dt,t1.b,t2.a,t2.b from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a=t2.a where t1.a is not null order by 1,2,3,4" + qt_int_has_is_null "select t1.dt,t1.b,t2.a,t2.b from split_join_for_null_skew_t t1 left join split_join_for_null_skew_t t2 on t1.a=t2.a where t1.a is null order by 1,2,3,4" + + // right join + qt_varchar "select t1.a,t1.b,t2.dt,t2.c from split_join_for_null_skew_t t1 right join split_join_for_null_skew_t t2 on t1.c=t2.c order by 1,2,3,4" + qt_datetime "select t2.b,t1.b,t2.a,t2.c from split_join_for_null_skew_t t1 right join split_join_for_null_skew_t t2 on t1.dt=t2.dt order by 1,2,3,4" + +} \ No newline at end of file