[fix](nereids) correlated anti join shouldn't be translated to null aware anti join (#24290)

original SQL
select t1.* from t1 where t1.k1 not in ( select t3.k1 from t3 where t1.k2 = t3.k2 );

rewrite SQL
before (wrong):
select t1.* from t1 null aware left anti join t2 on t1.k1 = t3.k1 and t1.k2 = t3.k2;
now (correct):
select t1.* from t1 left anti join t3 on t1.k2 = t3.k2 and (t1.k1 = t3.k1 or t3.k1 is null or t1.k1 is null);
This commit is contained in:
starocean999
2023-09-15 22:50:36 +08:00
committed by GitHub
parent 1c142309a6
commit 298bf0885d
3 changed files with 35 additions and 25 deletions

View File

@ -24,6 +24,7 @@ import org.apache.doris.nereids.trees.expressions.Alias;
import org.apache.doris.nereids.trees.expressions.EqualTo;
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.NamedExpression;
import org.apache.doris.nereids.trees.expressions.Not;
import org.apache.doris.nereids.trees.expressions.functions.agg.BitmapUnion;
@ -92,26 +93,33 @@ public class InApplyToJoin extends OneRewriteRuleFactory {
}
//in-predicate to equal
InSubquery inSubquery = ((InSubquery) apply.getSubqueryExpr());
Expression predicate;
Expression left = ((InSubquery) apply.getSubqueryExpr()).getCompareExpr();
Expression left = inSubquery.getCompareExpr();
// TODO: trick here, because when deep copy logical plan the apply right child
// is not same with query plan in subquery expr, since the scan node copy twice
Expression right = apply.getSubqueryExpr().getSubqueryOutput((LogicalPlan) apply.right());
Expression right = inSubquery.getSubqueryOutput((LogicalPlan) apply.right());
if (apply.isCorrelated()) {
predicate = ExpressionUtils.and(new EqualTo(left, right),
apply.getCorrelationFilter().get());
if (inSubquery.isNot()) {
predicate = ExpressionUtils.and(ExpressionUtils.or(new EqualTo(left, right),
new IsNull(left), new IsNull(right)),
apply.getCorrelationFilter().get());
} else {
predicate = ExpressionUtils.and(new EqualTo(left, right),
apply.getCorrelationFilter().get());
}
} else {
predicate = new EqualTo(left, right);
}
List<Expression> conjuncts = ExpressionUtils.extractConjunction(predicate);
if (((InSubquery) apply.getSubqueryExpr()).isNot()) {
if (inSubquery.isNot()) {
return new LogicalJoin<>(
predicate.nullable() ? JoinType.NULL_AWARE_LEFT_ANTI_JOIN : JoinType.LEFT_ANTI_JOIN,
Lists.newArrayList(),
conjuncts,
JoinHint.NONE, apply.getMarkJoinSlotReference(),
apply.children());
predicate.nullable() && !apply.isCorrelated()
? JoinType.NULL_AWARE_LEFT_ANTI_JOIN
: JoinType.LEFT_ANTI_JOIN,
Lists.newArrayList(), conjuncts, JoinHint.NONE,
apply.getMarkJoinSlotReference(), apply.children());
} else {
return new LogicalJoin<>(JoinType.LEFT_SEMI_JOIN, Lists.newArrayList(),
conjuncts,