Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[opt](Nereids) add where Null rule to create empty relation as where false (#38135) #38362

Merged
merged 2 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalEmptyRelation;
import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
Expand All @@ -45,12 +46,13 @@ public class EliminateFilter implements RewriteRuleFactory {
@Override
public List<Rule> buildRules() {
return ImmutableList.of(logicalFilter().when(
filter -> filter.getConjuncts().stream().anyMatch(BooleanLiteral.class::isInstance))
filter -> filter.getConjuncts().stream().anyMatch(BooleanLiteral.class::isInstance)
|| filter.getConjuncts().stream().anyMatch(NullLiteral.class::isInstance))
.thenApply(ctx -> {
LogicalFilter<Plan> filter = ctx.root;
ImmutableSet.Builder newConjuncts = ImmutableSet.builder();
for (Expression expression : filter.getConjuncts()) {
if (expression == BooleanLiteral.FALSE) {
if (expression == BooleanLiteral.FALSE || expression.isNullLiteral()) {
return new LogicalEmptyRelation(ctx.statementContext.getNextRelationId(),
filter.getOutput());
} else if (expression != BooleanLiteral.TRUE) {
Expand Down Expand Up @@ -80,7 +82,7 @@ public List<Rule> buildRules() {
Expression foldExpression =
FoldConstantRule.INSTANCE.rewrite(newExpr, context);

if (foldExpression == BooleanLiteral.FALSE) {
if (foldExpression == BooleanLiteral.FALSE || expression.isNullLiteral()) {
return new LogicalEmptyRelation(
ctx.statementContext.getNextRelationId(), filter.getOutput());
} else if (foldExpression != BooleanLiteral.TRUE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.doris.nereids.rules.rewrite;

import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
import org.apache.doris.nereids.util.LogicalPlanBuilder;
import org.apache.doris.nereids.util.MemoPatternMatchSupported;
Expand All @@ -42,6 +43,17 @@ void testEliminateFilterFalse() {
.matches(logicalEmptyRelation());
}

@Test
void testEliminateFilterNull() {
LogicalPlan filterNull = new LogicalPlanBuilder(PlanConstructor.newLogicalOlapScan(0, "t1", 0))
.filter(NullLiteral.INSTANCE)
.build();

PlanChecker.from(MemoTestUtils.createConnectContext(), filterNull)
.applyTopDown(new EliminateFilter())
.matches(logicalEmptyRelation());
}

@Test
void testEliminateFilterTrue() {
LogicalPlan filterTrue = new LogicalPlanBuilder(PlanConstructor.newLogicalOlapScan(0, "t1", 0))
Expand Down
89 changes: 89 additions & 0 deletions regression-test/data/empty_relation/eliminate_empty.out
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,95 @@ PhysicalResultSink

-- !except_empty_data --

-- !null_join --
PhysicalResultSink
--PhysicalEmptyRelation

-- !null_explain_union_empty_data --
PhysicalResultSink
--PhysicalDistribute
----hashAgg[LOCAL]
------PhysicalProject
--------PhysicalOlapScan[nation]

-- !null_union_empty_data --
1

-- !null_explain_union_empty_empty --
PhysicalResultSink
--PhysicalEmptyRelation

-- !null_union_empty_empty --

-- !null_union_emtpy_onerow --
10

-- !null_explain_intersect_data_empty --
PhysicalResultSink
--PhysicalEmptyRelation

-- !null_explain_intersect_empty_data --
PhysicalResultSink
--PhysicalEmptyRelation

-- !null_explain_except_data_empty --
PhysicalResultSink
--PhysicalDistribute
----PhysicalProject
------hashAgg[LOCAL]
--------PhysicalProject
----------PhysicalOlapScan[nation]

-- !null_explain_except_data_empty_data --
PhysicalResultSink
--PhysicalDistribute
----PhysicalExcept
------PhysicalDistribute
--------PhysicalProject
----------PhysicalOlapScan[nation]
------PhysicalDistribute
--------PhysicalProject
----------filter(( not (n_nationkey = 1)))
------------PhysicalOlapScan[nation]

-- !null_except_data_empty_data --
1

-- !null_explain_except_empty_data --
PhysicalResultSink
--PhysicalEmptyRelation

-- !null_intersect_data_empty --

-- !null_intersect_empty_data --

-- !null_except_data_empty --
1

-- !null_except_empty_data --

-- !prune_partition1 --
PhysicalResultSink
--PhysicalDistribute
----PhysicalProject
------hashAgg[GLOBAL]
--------PhysicalDistribute
----------hashAgg[LOCAL]
------------PhysicalProject
--------------filter((eliminate_partition_prune.k1 = 100))
----------------PhysicalOlapScan[eliminate_partition_prune]

-- !prune_partition2 --
PhysicalResultSink
--PhysicalDistribute
----PhysicalProject
------hashAgg[GLOBAL]
--------PhysicalDistribute
----------hashAgg[LOCAL]
------------PhysicalProject
--------------filter((eliminate_partition_prune.k1 = 100))
----------------PhysicalOlapScan[eliminate_partition_prune]

-- !join_with_empty_child --
2 8 e v 3
4 7 at 2
Expand Down
139 changes: 138 additions & 1 deletion regression-test/suites/empty_relation/eliminate_empty.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,143 @@ suite("eliminate_empty") {
select r_regionkey from region where false except select n_nationkey from nation
"""

qt_null_join """
explain shape plan
select *
from
nation
join
(select * from region where Null) R
"""

qt_null_explain_union_empty_data """
explain shape plan
select *
from (select n_nationkey from nation union select r_regionkey from region where Null) T
"""
qt_null_union_empty_data """
select *
from (select n_nationkey from nation union select r_regionkey from region where Null) T
"""

qt_null_explain_union_empty_empty """
explain shape plan
select *
from (
select n_nationkey from nation where Null
union
select r_regionkey from region where Null
) T
"""
qt_null_union_empty_empty """
select *
from (
select n_nationkey from nation where Null
union
select r_regionkey from region where Null
) T
"""
qt_null_union_emtpy_onerow """
select *
from (
select n_nationkey from nation where Null
union
select 10
union
select 10
)T
"""

qt_null_explain_intersect_data_empty """
explain shape plan
select n_nationkey from nation intersect select r_regionkey from region where Null
"""

qt_null_explain_intersect_empty_data """
explain shape plan
select r_regionkey from region where Null intersect select n_nationkey from nation
"""

qt_null_explain_except_data_empty """
explain shape plan
select n_nationkey from nation except select r_regionkey from region where Null
"""

qt_null_explain_except_data_empty_data """
explain shape plan
select n_nationkey from nation
except
select r_regionkey from region where Null
except
select n_nationkey from nation where n_nationkey != 1;
"""

qt_null_except_data_empty_data """
select n_nationkey from nation
except
select r_regionkey from region where Null
except
select n_nationkey from nation where n_nationkey != 1;
"""

qt_null_explain_except_empty_data """
explain shape plan
select r_regionkey from region where Null except select n_nationkey from nation
"""


qt_null_intersect_data_empty """
select n_nationkey from nation intersect select r_regionkey from region where Null
"""

qt_null_intersect_empty_data """
select r_regionkey from region where Null intersect select n_nationkey from nation
"""

qt_null_except_data_empty """
select n_nationkey from nation except select r_regionkey from region where Null
"""

qt_null_except_empty_data """
select r_regionkey from region where Null except select n_nationkey from nation
"""

sql """
drop table if exists eliminate_partition_prune;
"""
sql """
CREATE TABLE `eliminate_partition_prune` (
`k1` int(11) NULL COMMENT "",
`k2` int(11) NULL COMMENT "",
`k3` int(11) NULL COMMENT ""
)
PARTITION BY RANGE(`k1`, `k2`)
(PARTITION p1 VALUES LESS THAN ("3", "1"),
PARTITION p2 VALUES [("3", "1"), ("7", "10")),
PARTITION p3 VALUES [("7", "10"), ("10", "15")))
DISTRIBUTED BY HASH(`k1`) BUCKETS 10
PROPERTIES ('replication_num' = '1');
"""


qt_prune_partition1 """
explain shape plan
select sum(k2)
from
(select * from eliminate_partition_prune where k1=100) T
group by k3;
"""
sql """
insert into eliminate_partition_prune values (7, 0, 0)
"""
qt_prune_partition2 """
explain shape plan
select sum(k2)
from
(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"""

Expand Down Expand Up @@ -179,4 +316,4 @@ suite("eliminate_empty") {
sql """drop table if exists table_5_undef_partitions2_keys3"""
sql """drop table if exists table_10_undef_partitions2_keys3"""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ suite("test_multi_range_partition") {

explain {
sql "select * from pt where k1=7 and k2 in (null);"
contains "partitions=0/3"
contains "VEMPTYSET"
}

explain {
sql "select * from pt where k1=7 and k2 not in (null);"
contains "partitions=0/3"
contains "VEMPTYSET"
}

explain {
Expand All @@ -189,13 +189,13 @@ suite("test_multi_range_partition") {

explain {
sql "select * from pt where k2 in (null);"
contains "partitions=0/3"
contains "VEMPTYSET"
}

// p1/p2/p3 NOT pruned
explain {
sql "select * from pt where k2 not in (null)"
contains "partitions=0/3"
contains "VEMPTYSET"
}

explain {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,6 @@ suite("test_simplify_comparison") {
contains "CAST"
}

explain {
sql "verbose select * from simple_test_table_t where a = cast(1.1 as double) and b = cast(1.1 as double) and c = cast(1.1 as double) and d = cast(1.1 as double);"
contains "a[#0] IS NULL"
contains "b[#1] IS NULL"
contains "c[#2] IS NULL"
contains "d[#3] IS NULL"
contains "AND NULL"
}

explain {
sql "verbose select * from simple_test_table_t where e = cast(1.1 as double);"
contains "CAST(e[#4] AS double) = 1.1"
Expand Down Expand Up @@ -204,15 +195,6 @@ suite("test_simplify_comparison") {
contains "CAST"
}

explain {
sql "verbose select * from simple_test_table_t where a = 1.1 and b = 1.1 and c = 1.1 and d = 1.1;"
contains "a[#0] IS NULL"
contains "b[#1] IS NULL"
contains "c[#2] IS NULL"
contains "d[#3] IS NULL"
contains "AND NULL"
}

explain {
sql "verbose select * from simple_test_table_t where e = 1.1;"
contains "CAST(e[#4] AS double) = 1.1"
Expand Down
Loading