[feature](nereids)support one expression-rewrite rule: inPredicateToEqualTo (#12046)

Add one expression rewrite rule:
rewrite InPredicate to an EqualTo Expression, if there exists exactly one element in InPredicate Options.

Examples:
1. where A in (x) ==> where A = x
2. where A not in (x) ==> where not A = x
This commit is contained in:
Fy
2022-08-29 15:54:06 +08:00
committed by GitHub
parent 1d9d99c8ec
commit c0b56400ed
6 changed files with 91 additions and 3 deletions

View File

@ -18,6 +18,7 @@
package org.apache.doris.nereids.rules.expression.rewrite;
import org.apache.doris.nereids.rules.expression.rewrite.rules.BetweenToCompoundRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateToEqualToRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyCastRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
@ -35,6 +36,7 @@ public class ExpressionNormalization extends ExpressionRewrite {
public static final List<ExpressionRewriteRule> NORMALIZE_REWRITE_RULES = ImmutableList.of(
NormalizeBinaryPredicatesRule.INSTANCE,
BetweenToCompoundRule.INSTANCE,
InPredicateToEqualToRule.INSTANCE,
SimplifyNotExprRule.INSTANCE,
SimplifyCastRule.INSTANCE,
TypeCoercion.INSTANCE

View File

@ -0,0 +1,48 @@
// 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.EqualTo;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.InPredicate;
import java.util.List;
/**
* Rewrite InPredicate to an EqualTo Expression, if there exists exactly one element in InPredicate.options
* Examples:
* where A in (x) ==> where A = x
* where A not in (x) ==> where not A = x (After ExpressionTranslator, "not A = x" will be translated to "A != x")
*/
public class InPredicateToEqualToRule extends AbstractExpressionRewriteRule {
public static InPredicateToEqualToRule INSTANCE = new InPredicateToEqualToRule();
@Override
public Expression visitInPredicate(InPredicate inPredicate, ExpressionRewriteContext context) {
Expression left = inPredicate.getCompareExpr();
List<Expression> right = inPredicate.getOptions();
if (right.size() != 1) {
return new InPredicate(left.accept(this, context), right);
}
return new EqualTo(left.accept(this, context), right.get(0).accept(this, context));
}
}

View File

@ -39,10 +39,10 @@ public class InPredicate extends Expression {
private final Expression compareExpr;
private final List<Expression> options;
public InPredicate(Expression compareExpr, List<Expression> optionsList) {
super(new Builder<Expression>().add(compareExpr).addAll(optionsList).build().toArray(new Expression[0]));
public InPredicate(Expression compareExpr, List<Expression> options) {
super(new Builder<Expression>().add(compareExpr).addAll(options).build().toArray(new Expression[0]));
this.compareExpr = Objects.requireNonNull(compareExpr, "Compare Expr cannot be null");
this.options = ImmutableList.copyOf(Objects.requireNonNull(optionsList, "In list cannot be null"));
this.options = ImmutableList.copyOf(Objects.requireNonNull(options, "In list cannot be null"));
}
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {

View File

@ -21,6 +21,7 @@ import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.rules.expression.rewrite.rules.BetweenToCompoundRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.DistinctPredicatesRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.ExtractCommonFactorRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.InPredicateToEqualToRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyCastRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
@ -151,6 +152,28 @@ public class ExpressionRewriteTest {
}
@Test
public void testInPredicateToEqualToRule() {
executor = new ExpressionRuleExecutor(ImmutableList.of(InPredicateToEqualToRule.INSTANCE));
assertRewrite("a in (1)", "a = 1");
assertRewrite("a in (1, 2)", "a in (1, 2)");
assertRewrite("a not in (1)", "not a = 1");
assertRewrite("a not in (1, 2)", "not a in (1, 2)");
assertRewrite("a in (a in (1))", "a = (a = 1)");
assertRewrite("a in (a in (1, 2))", "a = (a in (1, 2))");
assertRewrite("(a in (1)) in (1)", "(a = 1) = 1");
assertRewrite("(a in (1, 2)) in (1)", "(a in (1, 2)) = 1");
assertRewrite("(a in (1)) in (1, 2)", "(a = 1) in (1, 2)");
assertRewrite("case a when b in (1) then a else c end in (1)",
"case a when b = 1 then a else c end = 1");
assertRewrite("case a when b not in (1) then a else c end not in (1)",
"not case a when not b = 1 then a else c end = 1");
assertRewrite("case a when b not in (1) then a else c end in (1, 2)",
"case a when not b = 1 then a else c end in (1, 2)");
}
@Test
public void testSimplifyCastRule() {
executor = new ExpressionRuleExecutor(ImmutableList.of(SimplifyCastRule.INSTANCE));

View File

@ -24,3 +24,10 @@
29 Supplier#000000029 VVSymB3fbwaN ARGENTINA4 ARGENTINA AMERICA 11-773-203-7342
9 Supplier#000000009 ,gJ6K2MKveYxQT IRAN 6 IRAN MIDDLE EAST 20-338-906-3675
-- !in_predicate_9 --
15 Supplier#000000015 DF35PepL5saAK INDIA 0 INDIA ASIA 18-687-542-7601
-- !in_predicate_10 --
29 Supplier#000000029 VVSymB3fbwaN ARGENTINA4 ARGENTINA AMERICA 11-773-203-7342
9 Supplier#000000009 ,gJ6K2MKveYxQT IRAN 6 IRAN MIDDLE EAST 20-338-906-3675

View File

@ -55,5 +55,13 @@ suite("inpredicate") {
order_qt_in_predicate_8 """
SELECT * FROM supplier WHERE s_nation not in ('PERU', 'ETHIOPIA');
"""
order_qt_in_predicate_9 """
SELECT * FROM supplier WHERE s_suppkey in (15);
"""
order_qt_in_predicate_10 """
SELECT * FROM supplier WHERE s_suppkey not in (15);
"""
}