[enhancement](nereids) add betweentocompound rewrite rule for ssb (#10630)
add betweentocompound rewrite rule for ssb. for example: 1. A BETWEEN X AND Y ==> A >= X AND A <= Y 2. A NOT BETWEEN X AND Y ==> A < X OR A > Y
This commit is contained in:
@ -18,6 +18,7 @@
|
||||
package org.apache.doris.nereids.jobs;
|
||||
|
||||
import org.apache.doris.nereids.PlannerContext;
|
||||
import org.apache.doris.nereids.rules.analysis.BindFunction;
|
||||
import org.apache.doris.nereids.rules.analysis.BindRelation;
|
||||
import org.apache.doris.nereids.rules.analysis.BindSlotReference;
|
||||
|
||||
@ -37,7 +38,8 @@ public class AnalyzeRulesJob extends BatchRulesJob {
|
||||
rulesJob.addAll(ImmutableList.of(
|
||||
bottomUpBatch(ImmutableList.of(
|
||||
new BindRelation(),
|
||||
new BindSlotReference())
|
||||
new BindSlotReference(),
|
||||
new BindFunction())
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,8 @@
|
||||
|
||||
package org.apache.doris.nereids.rules.expression.rewrite;
|
||||
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeExpressionRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.BetweenToCompoundRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
|
||||
@ -32,8 +33,9 @@ import java.util.List;
|
||||
public class ExpressionRuleExecutor {
|
||||
|
||||
public static final List<ExpressionRewriteRule> REWRITE_RULES = ImmutableList.of(
|
||||
new BetweenToCompoundRule(),
|
||||
new SimplifyNotExprRule(),
|
||||
new NormalizeExpressionRule()
|
||||
new NormalizeBinaryPredicatesRule()
|
||||
);
|
||||
|
||||
private final ExpressionRewriteContext ctx;
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
// 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.expression.rewrite.rules;
|
||||
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
|
||||
import org.apache.doris.nereids.trees.expressions.And;
|
||||
import org.apache.doris.nereids.trees.expressions.Between;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
|
||||
import org.apache.doris.nereids.trees.expressions.LessThanEqual;
|
||||
|
||||
/**
|
||||
* Rewrites BetweenPredicates into an equivalent conjunctive CompoundPredicate,
|
||||
* "not between" is first processed by the BetweenToCompoundRule and then by the SimplifyNotExprRule.
|
||||
* Examples:
|
||||
* A BETWEEN X AND Y ==> A >= X AND A <= Y
|
||||
*/
|
||||
public class BetweenToCompoundRule extends AbstractExpressionRewriteRule {
|
||||
|
||||
public static BetweenToCompoundRule INSTANCE = new BetweenToCompoundRule();
|
||||
|
||||
@Override
|
||||
public Expression visitBetween(Between expr, ExpressionRewriteContext context) {
|
||||
Expression left = new GreaterThanEqual<>(expr.getCompareExpr(), expr.getLowerBound());
|
||||
Expression right = new LessThanEqual<>(expr.getCompareExpr(), expr.getUpperBound());
|
||||
return new And<>(left, right);
|
||||
}
|
||||
}
|
||||
@ -34,9 +34,9 @@ import org.apache.doris.nereids.trees.expressions.LessThanEqual;
|
||||
* For example:
|
||||
* 5 > id -> id < 5
|
||||
*/
|
||||
public class NormalizeExpressionRule extends AbstractExpressionRewriteRule {
|
||||
public class NormalizeBinaryPredicatesRule extends AbstractExpressionRewriteRule {
|
||||
|
||||
public static NormalizeExpressionRule INSTANCE = new NormalizeExpressionRule();
|
||||
public static NormalizeBinaryPredicatesRule INSTANCE = new NormalizeBinaryPredicatesRule();
|
||||
|
||||
@Override
|
||||
public Expression visitComparisonPredicate(ComparisonPredicate expr, ExpressionRewriteContext context) {
|
||||
@ -20,13 +20,16 @@ package org.apache.doris.nereids.rules.expression.rewrite.rules;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.AbstractExpressionRewriteRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.ExpressionRewriteContext;
|
||||
import org.apache.doris.nereids.trees.NodeType;
|
||||
import org.apache.doris.nereids.trees.expressions.And;
|
||||
import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
|
||||
import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.GreaterThan;
|
||||
import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
|
||||
import org.apache.doris.nereids.trees.expressions.LessThan;
|
||||
import org.apache.doris.nereids.trees.expressions.LessThanEqual;
|
||||
import org.apache.doris.nereids.trees.expressions.Not;
|
||||
import org.apache.doris.nereids.trees.expressions.Or;
|
||||
|
||||
/**
|
||||
* Rewrite rule of NOT expression.
|
||||
@ -39,6 +42,8 @@ import org.apache.doris.nereids.trees.expressions.Not;
|
||||
* not a >= b -> a < b.
|
||||
* not a <= b -> a > b.
|
||||
* not a=b -> not a=b.
|
||||
* not and(a >= b, a <= c) -> or(a < b, a > c)
|
||||
* not or(a >= b, a <= c) -> and(a < b, a > c)
|
||||
*/
|
||||
public class SimplifyNotExprRule extends AbstractExpressionRewriteRule {
|
||||
|
||||
@ -66,6 +71,19 @@ public class SimplifyNotExprRule extends AbstractExpressionRewriteRule {
|
||||
default:
|
||||
return expr;
|
||||
}
|
||||
} else if (child instanceof CompoundPredicate) {
|
||||
CompoundPredicate cp = (CompoundPredicate) expr.child();
|
||||
Expression left = rewrite(new Not(cp.left()), context);
|
||||
Expression right = rewrite(new Not(cp.right()), context);
|
||||
NodeType type = cp.getType();
|
||||
switch (type) {
|
||||
case AND:
|
||||
return new Or<>(left, right);
|
||||
case OR:
|
||||
return new And<>(left, right);
|
||||
default:
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
||||
if (child instanceof Not) {
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
package org.apache.doris.nereids.rules.expression.rewrite;
|
||||
|
||||
import org.apache.doris.nereids.parser.NereidsParser;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeExpressionRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
|
||||
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
|
||||
@ -47,7 +47,7 @@ public class ExpressionRewriteTest {
|
||||
|
||||
@Test
|
||||
public void testNormalizeExpressionRewrite() {
|
||||
executor = new ExpressionRuleExecutor(NormalizeExpressionRule.INSTANCE);
|
||||
executor = new ExpressionRuleExecutor(NormalizeBinaryPredicatesRule.INSTANCE);
|
||||
|
||||
assertRewrite("2 > x", "x < 2");
|
||||
assertRewrite("2 >= x", "x <= 2");
|
||||
|
||||
@ -35,10 +35,13 @@ import org.apache.doris.nereids.operators.plans.logical.LogicalProject;
|
||||
import org.apache.doris.nereids.properties.PhysicalProperties;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.trees.expressions.Add;
|
||||
import org.apache.doris.nereids.trees.expressions.And;
|
||||
import org.apache.doris.nereids.trees.expressions.Between;
|
||||
import org.apache.doris.nereids.trees.expressions.EqualTo;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.GreaterThan;
|
||||
import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
|
||||
import org.apache.doris.nereids.trees.expressions.LessThanEqual;
|
||||
import org.apache.doris.nereids.trees.expressions.Literal;
|
||||
import org.apache.doris.nereids.trees.expressions.Subtract;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
@ -215,6 +218,11 @@ public class PushDownPredicateTest implements Plans {
|
||||
Expression whereCondition2 = new EqualTo<>(rScore.getOutput().get(1), rCourse.getOutput().get(0));
|
||||
// student.age between 18 and 20
|
||||
Expression whereCondition3 = new Between<>(rStudent.getOutput().get(2), Literal.of(18), Literal.of(20));
|
||||
// student.age >= 18 and student.age <= 20
|
||||
Expression whereCondition3result = new And<>(
|
||||
new GreaterThanEqual<>(rStudent.getOutput().get(2), Literal.of(18)),
|
||||
new LessThanEqual<>(rStudent.getOutput().get(2), Literal.of(20)));
|
||||
|
||||
// score.grade > 60
|
||||
Expression whereCondition4 = new GreaterThan<>(rScore.getOutput().get(2), Literal.of(60));
|
||||
|
||||
@ -256,7 +264,7 @@ public class PushDownPredicateTest implements Plans {
|
||||
|
||||
Assertions.assertEquals(((LogicalJoin) join2).getCondition().get(), whereCondition2);
|
||||
Assertions.assertEquals(((LogicalJoin) join3).getCondition().get(), whereCondition1);
|
||||
Assertions.assertEquals(((LogicalFilter) op1).getPredicates(), whereCondition3);
|
||||
Assertions.assertEquals(((LogicalFilter) op1).getPredicates().sql(), whereCondition3result.sql());
|
||||
Assertions.assertEquals(((LogicalFilter) op2).getPredicates(), whereCondition4);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user