[fix](nereids)SubqueryToApply rule lost is null condition (#20971)
* [fix](nereids)SubqueryToApply rule lost is null condition
This commit is contained in:
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
-- This file is automatically generated. You should know what you did if you want to edit this
|
||||
-- !sql --
|
||||
|
||||
@ -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;
|
||||
"""
|
||||
}
|
||||
Reference in New Issue
Block a user