[fix](nereids)SubqueryToApply rule lost is null condition (#20971)

* [fix](nereids)SubqueryToApply rule lost is null condition
This commit is contained in:
starocean999
2023-06-19 23:43:40 +08:00
committed by GitHub
parent be8fb68712
commit e6f50c04f1
4 changed files with 75 additions and 19 deletions

View File

@ -29,6 +29,7 @@ import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
import org.apache.doris.nereids.trees.expressions.Exists;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.InSubquery;
import org.apache.doris.nereids.trees.expressions.IsNull;
import org.apache.doris.nereids.trees.expressions.MarkJoinSlotReference;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.Not;
@ -356,6 +357,21 @@ public class SubqueryToApply implements AnalysisRuleFactory {
return visit(not, context);
}
@Override
public Expression visitIsNull(IsNull isNull, SubqueryContext context) {
// Need to re-update scalarSubQuery unequal conditions into subqueryCorrespondingConject
if (isNull.child() instanceof BinaryOperator
&& (((BinaryOperator) isNull.child()).left().containsType(ScalarSubquery.class)
|| ((BinaryOperator) isNull.child()).right().containsType(ScalarSubquery.class))) {
Expression newChild = replace(isNull.child(), context);
ScalarSubquery subquery = collectScalarSubqueryForBinaryOperator((BinaryOperator) isNull.child());
context.updateSubqueryCorrespondingConjunctIsNull(subquery);
return context.getSubqueryToMarkJoinSlotValue(subquery).isPresent() ? newChild : new IsNull(newChild);
}
return visit(isNull, context);
}
@Override
public Expression visitBinaryOperator(BinaryOperator binaryOperator, SubqueryContext context) {
boolean atLeastOneChildContainsScalarSubquery =
@ -403,39 +419,46 @@ public class SubqueryToApply implements AnalysisRuleFactory {
subqueryExprs.forEach(subqueryExpr -> subqueryToMarkJoinSlot.put(subqueryExpr, Optional.empty()));
}
public Map<SubqueryExpr, Optional<MarkJoinSlotReference>> getSubqueryToMarkJoinSlot() {
private Map<SubqueryExpr, Optional<MarkJoinSlotReference>> getSubqueryToMarkJoinSlot() {
return subqueryToMarkJoinSlot;
}
public Map<SubqueryExpr, Expression> getSubqueryCorrespondingConjunct() {
private Map<SubqueryExpr, Expression> getSubqueryCorrespondingConjunct() {
return subqueryCorrespondingConjunct;
}
public Optional<MarkJoinSlotReference> getSubqueryToMarkJoinSlotValue(SubqueryExpr subqueryExpr) {
private Optional<MarkJoinSlotReference> getSubqueryToMarkJoinSlotValue(SubqueryExpr subqueryExpr) {
return subqueryToMarkJoinSlot.get(subqueryExpr);
}
public void setSubqueryToMarkJoinSlot(SubqueryExpr subquery,
private void setSubqueryToMarkJoinSlot(SubqueryExpr subquery,
Optional<MarkJoinSlotReference> markJoinSlotReference) {
subqueryToMarkJoinSlot.put(subquery, markJoinSlotReference);
}
public void setSubqueryCorrespondingConject(SubqueryExpr subquery,
private void setSubqueryCorrespondingConject(SubqueryExpr subquery,
Expression expression) {
subqueryCorrespondingConjunct.put(subquery, expression);
}
public boolean onlySingleSubquery() {
private boolean onlySingleSubquery() {
return subqueryToMarkJoinSlot.size() == 1;
}
public void updateSubqueryCorrespondingConjunctInNot(SubqueryExpr subquery) {
private void updateSubqueryCorrespondingConjunctInNot(SubqueryExpr subquery) {
if (subqueryCorrespondingConjunct.containsKey(subquery)) {
subqueryCorrespondingConjunct.replace(subquery,
new Not(subqueryCorrespondingConjunct.get(subquery)));
}
}
private void updateSubqueryCorrespondingConjunctIsNull(SubqueryExpr subquery) {
if (subqueryCorrespondingConjunct.containsKey(subquery)) {
subqueryCorrespondingConjunct.replace(subquery,
new IsNull(subqueryCorrespondingConjunct.get(subquery)));
}
}
/**
* For scalarSubQuery and MarkJoin, it will be replaced by markSlotReference
* e.g.
@ -443,7 +466,7 @@ public class SubqueryToApply implements AnalysisRuleFactory {
* -->
* logicalFilter(predicate=$c$1 or $c$2)
*/
public Expression replaceBinaryOperator(BinaryOperator binaryOperator,
private Expression replaceBinaryOperator(BinaryOperator binaryOperator,
Expression left,
Expression right,
boolean isProject) {

View File

@ -402,18 +402,18 @@ public class PlannerTest extends TestWithFeService {
Assertions.assertEquals(plan1, plan2);
};
compare.accept("select * from db1.tbl2 where k1 = 2.0", "select * from db1.tbl2 where k1 = 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where k1 = 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where k1 = 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where k1 = 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where 2 = 2.1");
compare.accept("select * from db1.tbl2 where k1 != 2.0", "select * from db1.tbl2 where k1 != 2");
compare.accept("select * from db1.tbl2 where k1 != 2.1", "select * from db1.tbl2 where TRUE");
compare.accept("select * from db1.tbl2 where k1 <= 2.0", "select * from db1.tbl2 where k1 <= 2");
compare.accept("select * from db1.tbl2 where k1 <= 2.1", "select * from db1.tbl2 where k1 <= 2");
compare.accept("select * from db1.tbl2 where k1 >= 2.0", "select * from db1.tbl2 where k1 >= 2");
compare.accept("select * from db1.tbl2 where k1 >= 2.1", "select * from db1.tbl2 where k1 > 2");
compare.accept("select * from db1.tbl2 where k1 < 2.0", "select * from db1.tbl2 where k1 < 2");
compare.accept("select * from db1.tbl2 where k1 < 2.1", "select * from db1.tbl2 where k1 <= 2");
compare.accept("select * from db1.tbl2 where k1 > 2.0", "select * from db1.tbl2 where k1 > 2");
compare.accept("select * from db1.tbl2 where k1 > 2.1", "select * from db1.tbl2 where k1 > 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 != 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 != 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 != 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where TRUE");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 >= 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 >= 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 >= 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 < 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 < 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 < 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2");
compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2");
}
@Test

View File

@ -0,0 +1,3 @@
-- This file is automatically generated. You should know what you did if you want to edit this
-- !sql --

View File

@ -0,0 +1,30 @@
// 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("join_subquery_to_apply") {
sql 'set enable_nereids_planner=true'
sql 'set enable_fallback_to_original_planner=false'
qt_sql"""
select
ref_25.`user_name` as c3
from
(select 'zhangsan' as user_name) as ref_25
where
bitxor(cast(find_in_set(cast(coalesce(hex(cast((select 211985) as bigint)), ref_25.`user_name`) as varchar), 'zhangsan') as int), 1) is NULL;
"""
}