You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by hu...@apache.org on 2022/07/21 04:35:33 UTC
[doris] branch master updated: [Enhancement](Nereids) add some expr rewrite rule and plan rewrite rule of rewrite its expression (#10667)
This is an automated email from the ASF dual-hosted git repository.
huajianlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new f8ad2613cf [Enhancement](Nereids) add some expr rewrite rule and plan rewrite rule of rewrite its expression (#10667)
f8ad2613cf is described below
commit f8ad2613cf476cc42eb3aa09cd92e51b7ef20110
Author: shee <13...@users.noreply.github.com>
AuthorDate: Thu Jul 21 12:35:28 2022 +0800
[Enhancement](Nereids) add some expr rewrite rule and plan rewrite rule of rewrite its expression (#10667)
# first: Add two expr rewrite rule:
1. remove duplicate expr
a = 1 and a = 1 -> a = 1
2. extract common expr
(a or b) and (a or c) -> a or (b and c)
# second: Add some plan rewrite rule of rewriting expr of operator
1. NormalizeExpressionOfPlan contains normalize expr rewrite rule. Using these normalizerule rewrite LogicalFilter、LogicalAggravate,LogicalProject,LogicalJoin exprs
2. OptimizeExpressionOfPlan contains optimize expr rewrite rule. Using these optimize rule rewrite LogicalFilter、LogicalAggravate,LogicalProject,LogicalJoin exprs
---
.../apache/doris/nereids/analyzer/UnboundSlot.java | 5 +
.../org/apache/doris/nereids/rules/RuleType.java | 5 +
.../rewrite/ExpressionOfPlanRewrite.java | 121 +++++++++++++++++++++
.../expression/rewrite/ExpressionRuleExecutor.java | 5 +
.../rewrite/NormalizeExpressionOfPlan.java | 41 +++++++
.../rewrite/OptimizeExpressionOfPlan.java | 41 +++++++
.../rewrite/rules/DistinctPredicatesRule.java | 52 +++++++++
.../rewrite/rules/ExtractCommonFactorRule.java | 76 +++++++++++++
.../trees/expressions/CompoundPredicate.java | 4 +-
.../apache/doris/nereids/util/ExpressionUtils.java | 6 +-
.../expression/rewrite/ExpressionRewriteTest.java | 106 ++++++++++++++++--
11 files changed, 451 insertions(+), 11 deletions(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java
index 2fc8b1fc97..1cf0a81265 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java
@@ -84,6 +84,11 @@ public class UnboundSlot extends Slot implements Unbound {
return Objects.hash(nameParts);
}
+ @Override
+ public int hashCode() {
+ return Objects.hash(nameParts.toArray());
+ }
+
@Override
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitUnboundSlot(this, context);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
index 2119a1e265..6d1f55ea32 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java
@@ -46,6 +46,11 @@ public enum RuleType {
COLUMN_PRUNE_FILTER_CHILD(RuleTypeClass.REWRITE),
COLUMN_PRUNE_SORT_CHILD(RuleTypeClass.REWRITE),
COLUMN_PRUNE_JOIN_CHILD(RuleTypeClass.REWRITE),
+ // expression of plan rewrite
+ REWRITE_PROJECT_EXPRESSION(RuleTypeClass.REWRITE),
+ REWRITE_AGG_EXPRESSION(RuleTypeClass.REWRITE),
+ REWRITE_FILTER_EXPRESSION(RuleTypeClass.REWRITE),
+ REWRITE_JOIN_EXPRESSION(RuleTypeClass.REWRITE),
REORDER_JOIN(RuleTypeClass.REWRITE),
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOfPlanRewrite.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOfPlanRewrite.java
new file mode 100644
index 0000000000..d4f91b2155
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionOfPlanRewrite.java
@@ -0,0 +1,121 @@
+// 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;
+
+import org.apache.doris.nereids.rules.Rule;
+import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
+import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
+import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
+import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * expression of plan rewrite rule.
+ */
+public class ExpressionOfPlanRewrite implements RewriteRuleFactory {
+ private final ExpressionRuleExecutor rewriter;
+
+ public ExpressionOfPlanRewrite(ExpressionRuleExecutor rewriter) {
+ this.rewriter = Objects.requireNonNull(rewriter, "rewriter is null");
+ }
+
+ @Override
+ public List<Rule> buildRules() {
+ return ImmutableList.of(
+ new ProjectExpressionRewrite().build(),
+ new AggExpressionRewrite().build(),
+ new FilterExpressionRewrite().build(),
+ new JoinExpressionRewrite().build());
+ }
+
+
+ private class ProjectExpressionRewrite extends OneRewriteRuleFactory {
+ @Override
+ public Rule build() {
+ return logicalProject().then(project -> {
+ List<NamedExpression> projects = project.getProjects();
+ List<NamedExpression> newProjects = projects.stream()
+ .map(expr -> (NamedExpression) rewriter.rewrite(expr)).collect(Collectors.toList());
+ if (projects.containsAll(newProjects)) {
+ return project;
+ }
+ return new LogicalProject<>(newProjects, project.child());
+ }).toRule(RuleType.REWRITE_PROJECT_EXPRESSION);
+ }
+ }
+
+ private class FilterExpressionRewrite extends OneRewriteRuleFactory {
+ @Override
+ public Rule build() {
+ return logicalFilter().then(filter -> {
+ Expression newExpr = rewriter.rewrite(filter.getPredicates());
+ if (newExpr.equals(filter.getPredicates())) {
+ return filter;
+ }
+ return new LogicalFilter<>(newExpr, filter.child());
+ }).toRule(RuleType.REWRITE_FILTER_EXPRESSION);
+ }
+ }
+
+ private class AggExpressionRewrite extends OneRewriteRuleFactory {
+ @Override
+ public Rule build() {
+ return logicalAggregate().then(agg -> {
+ List<Expression> groupByExprs = agg.getGroupByExpressionList();
+ List<Expression> newGroupByExprs = rewriter.rewrite(groupByExprs);
+
+ List<NamedExpression> outputExpressions = agg.getOutputExpressionList();
+ List<NamedExpression> newOutputExpressions = outputExpressions.stream()
+ .map(expr -> (NamedExpression) rewriter.rewrite(expr)).collect(Collectors.toList());
+ if (outputExpressions.containsAll(newOutputExpressions)) {
+ return agg;
+ }
+ return new LogicalAggregate<>(newGroupByExprs, newOutputExpressions, agg.isDisassembled(),
+ agg.getAggPhase(), agg.child());
+ }).toRule(RuleType.REWRITE_AGG_EXPRESSION);
+ }
+ }
+
+ private class JoinExpressionRewrite extends OneRewriteRuleFactory {
+ @Override
+ public Rule build() {
+ return logicalJoin().then(join -> {
+ Optional<Expression> condition = join.getCondition();
+ if (!condition.isPresent()) {
+ return join;
+ }
+ Expression newCondition = rewriter.rewrite(condition.get());
+ if (newCondition.equals(condition.get())) {
+ return join;
+ }
+ return new LogicalJoin<>(join.getJoinType(), Optional.of(newCondition), join.left(), join.right());
+ }).toRule(RuleType.REWRITE_JOIN_EXPRESSION);
+ }
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java
index 65b5a9bd5e..d2e66a2c3e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRuleExecutor.java
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Expression rewrite entry, which contains all rewrite rules.
@@ -56,6 +57,10 @@ public class ExpressionRuleExecutor {
this.ctx = new ExpressionRewriteContext();
}
+ public List<Expression> rewrite(List<Expression> exprs) {
+ return exprs.stream().map(this::rewrite).collect(Collectors.toList());
+ }
+
/**
* Given an expression, returns a rewritten expression.
*/
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/NormalizeExpressionOfPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/NormalizeExpressionOfPlan.java
new file mode 100644
index 0000000000..44970483f9
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/NormalizeExpressionOfPlan.java
@@ -0,0 +1,41 @@
+// 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;
+
+import org.apache.doris.nereids.rules.expression.rewrite.rules.BetweenToCompoundRule;
+import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeBinaryPredicatesRule;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * normalize expression of plan rule set.
+ */
+public class NormalizeExpressionOfPlan extends ExpressionOfPlanRewrite {
+
+ public static final List<ExpressionRewriteRule> NORMALIZE_REWRITE_RULES = ImmutableList.of(
+ NormalizeBinaryPredicatesRule.INSTANCE,
+ BetweenToCompoundRule.INSTANCE
+ );
+ private static final ExpressionRuleExecutor EXECUTOR = new ExpressionRuleExecutor(NORMALIZE_REWRITE_RULES);
+
+ public NormalizeExpressionOfPlan() {
+ super(EXECUTOR);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/OptimizeExpressionOfPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/OptimizeExpressionOfPlan.java
new file mode 100644
index 0000000000..44bb3ed06e
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/OptimizeExpressionOfPlan.java
@@ -0,0 +1,41 @@
+// 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;
+
+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.SimplifyNotExprRule;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * optimize expression of plan rule set.
+ */
+public class OptimizeExpressionOfPlan extends ExpressionOfPlanRewrite {
+ public static final List<ExpressionRewriteRule> OPTIMIZE_REWRITE_RULES = ImmutableList.of(
+ SimplifyNotExprRule.INSTANCE,
+ ExtractCommonFactorRule.INSTANCE,
+ DistinctPredicatesRule.INSTANCE);
+ private static final ExpressionRuleExecutor EXECUTOR = new ExpressionRuleExecutor(OPTIMIZE_REWRITE_RULES);
+
+ public OptimizeExpressionOfPlan() {
+ super(EXECUTOR);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DistinctPredicatesRule.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DistinctPredicatesRule.java
new file mode 100644
index 0000000000..fd78f18057
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/DistinctPredicatesRule.java
@@ -0,0 +1,52 @@
+// 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.CompoundPredicate;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.util.ExpressionUtils;
+
+import com.google.common.collect.Lists;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Remove redundant expr for 'CompoundPredicate'.
+ * for example:
+ * transform (a = 1) and (b > 2) and (a = 1) to (a = 1) and (b > 2)
+ * transform (a = 1) or (a = 1) to (a = 1)
+ */
+public class DistinctPredicatesRule extends AbstractExpressionRewriteRule {
+
+ public static final DistinctPredicatesRule INSTANCE = new DistinctPredicatesRule();
+
+ @Override
+ public Expression visitCompoundPredicate(CompoundPredicate expr, ExpressionRewriteContext context) {
+ List<Expression> extractExpressions = ExpressionUtils.extract(expr);
+ Set<Expression> distinctExpressions = new LinkedHashSet<>(extractExpressions);
+ if (distinctExpressions.size() != extractExpressions.size()) {
+ return ExpressionUtils.combine(expr.getType(), Lists.newArrayList(distinctExpressions));
+ }
+ return expr;
+ }
+}
+
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ExtractCommonFactorRule.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ExtractCommonFactorRule.java
new file mode 100644
index 0000000000..ff65017161
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/ExtractCommonFactorRule.java
@@ -0,0 +1,76 @@
+// 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.CompoundPredicate;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.util.ExpressionUtils;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Extract common expr for `CompoundPredicate`.
+ * for example:
+ * transform (a or b) and (a or c) to a or (b and c)
+ * transform (a and b) or (a and c) to a and (b or c)
+ */
+public class ExtractCommonFactorRule extends AbstractExpressionRewriteRule {
+
+ public static final ExtractCommonFactorRule INSTANCE = new ExtractCommonFactorRule();
+
+ @Override
+ public Expression visitCompoundPredicate(CompoundPredicate expr, ExpressionRewriteContext context) {
+
+ Expression rewrittenChildren = ExpressionUtils.combine(expr.getType(), ExpressionUtils.extract(expr).stream()
+ .map(predicate -> rewrite(predicate, context)).collect(Collectors.toList()));
+
+ if (!(rewrittenChildren instanceof CompoundPredicate)) {
+ return rewrittenChildren;
+ }
+
+ CompoundPredicate compoundPredicate = (CompoundPredicate) rewrittenChildren;
+
+ List<List<Expression>> partitions = ExpressionUtils.extract(compoundPredicate).stream()
+ .map(predicate -> predicate instanceof CompoundPredicate ? ExpressionUtils.extract(
+ (CompoundPredicate) predicate) : Lists.newArrayList(predicate)).collect(Collectors.toList());
+
+ Set<Expression> commons = partitions.stream().map(predicates -> predicates.stream().collect(Collectors.toSet()))
+ .reduce(Sets::intersection).orElse(Collections.emptySet());
+
+ List<List<Expression>> uncorrelated = partitions.stream()
+ .map(predicates -> predicates.stream().filter(p -> !commons.contains(p)).collect(Collectors.toList()))
+ .collect(Collectors.toList());
+
+ Expression combineUncorrelated = ExpressionUtils.combine(compoundPredicate.getType(),
+ uncorrelated.stream().map(predicates -> ExpressionUtils.combine(compoundPredicate.flip(), predicates))
+ .collect(Collectors.toList()));
+
+ List<Expression> finalCompound = Lists.newArrayList(commons);
+ finalCompound.add(combineUncorrelated);
+
+ return ExpressionUtils.combine(compoundPredicate.flip(), finalCompound);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java
index 22e47f1d3d..a9819a2fd9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/CompoundPredicate.java
@@ -27,7 +27,7 @@ import java.util.Objects;
* Compound predicate expression.
* Such as &&,||,AND,OR.
*/
-public class CompoundPredicate extends Expression implements BinaryExpression {
+public abstract class CompoundPredicate extends Expression implements BinaryExpression {
/**
* Desc: Constructor for CompoundPredicate.
@@ -58,7 +58,7 @@ public class CompoundPredicate extends Expression implements BinaryExpression {
@Override
public Expression withChildren(List<Expression> children) {
- return new CompoundPredicate(getType(), children.get(0), children.get(1));
+ throw new RuntimeException("The withChildren() method is not implemented");
}
@Override
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
index 7c002371c3..74032cedaa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
@@ -17,10 +17,12 @@
package org.apache.doris.nereids.util;
+import org.apache.doris.nereids.trees.expressions.And;
import org.apache.doris.nereids.trees.expressions.BooleanLiteral;
import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.ExpressionType;
+import org.apache.doris.nereids.trees.expressions.Or;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
@@ -98,8 +100,8 @@ public class ExpressionUtils {
}
}
- Optional<Expression> result =
- distinctExpressions.stream().reduce((left, right) -> new CompoundPredicate(op, left, right));
+ Optional<Expression> result = distinctExpressions.stream()
+ .reduce(op == ExpressionType.AND ? And::new : Or::new);
return result.orElse(new BooleanLiteral(op == ExpressionType.AND));
}
}
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
index 792e33cdeb..50c8bf3f81 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java
@@ -18,10 +18,14 @@
package org.apache.doris.nereids.rules.expression.rewrite;
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.NormalizeBinaryPredicatesRule;
import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule;
import org.apache.doris.nereids.trees.expressions.Expression;
+import com.google.common.collect.ImmutableList;
import org.junit.Assert;
import org.junit.Test;
@@ -36,13 +40,24 @@ public class ExpressionRewriteTest {
public void testNotRewrite() {
executor = new ExpressionRuleExecutor(SimplifyNotExprRule.INSTANCE);
- assertRewrite("not x > y", "x <= y");
- assertRewrite("not x < y", "x >= y");
- assertRewrite("not x >= y", "x < y");
- assertRewrite("not x <= y", "x > y");
- assertRewrite("not x = y", "not x = y");
- assertRewrite("not not x > y", "x > y");
- assertRewrite("not not not x > y", "x <= y");
+ assertRewrite("not x", "not x");
+ assertRewrite("not not x", "x");
+ assertRewrite("not not not x", "not x");
+ assertRewrite("not (x > y)", "x <= y");
+ assertRewrite("not (x < y)", "x >= y");
+ assertRewrite("not (x >= y)", "x < y");
+ assertRewrite("not (x <= y)", "x > y");
+ assertRewrite("not (x = y)", "not (x = y)");
+ assertRewrite("not not (x > y)", "x > y");
+ assertRewrite("not not not (x > y)", "x <= y");
+ assertRewrite("not not not (x > (not not y))", "x <= y");
+ assertRewrite("not (x > (not not y))", "x <= y");
+
+ assertRewrite("not (a and b)", "(not a) or (not b)");
+ assertRewrite("not (a or b)", "(not a) and (not b)");
+
+ assertRewrite("not (a and b and (c or d))", "(not a) or (not b) or ((not c) and (not d))");
+
}
@Test
@@ -56,6 +71,83 @@ public class ExpressionRewriteTest {
assertRewrite("2 = x", "x = 2");
}
+ @Test
+ public void testDistinctPredicatesRewrite() {
+ executor = new ExpressionRuleExecutor(DistinctPredicatesRule.INSTANCE);
+
+ assertRewrite("a = 1", "a = 1");
+ assertRewrite("a = 1 and a = 1", "a = 1");
+ assertRewrite("a = 1 and b > 2 and a = 1", "a = 1 and b > 2");
+ assertRewrite("a = 1 and a = 1 and b > 2 and a = 1 and a = 1", "a = 1 and b > 2");
+ assertRewrite("a = 1 or a = 1", "a = 1");
+ assertRewrite("a = 1 or a = 1 or b >= 1", "a = 1 or b >= 1");
+ }
+
+
+ @Test
+ public void testExtractCommonFactorRewrite() {
+ executor = new ExpressionRuleExecutor(ExtractCommonFactorRule.INSTANCE);
+
+ assertRewrite("a", "a");
+
+ assertRewrite("a = 1", "a = 1");
+ assertRewrite("a and b", "a and b");
+ assertRewrite("a = 1 and b > 2", "a = 1 and b > 2");
+
+
+ assertRewrite("(a and b) or (c and d)", "(a and b) or (c and d)");
+ assertRewrite("(a and b) and (c and d)", "((a and b) and c) and d");
+
+ assertRewrite("(a or b) and (a or c)", "a or (b and c)");
+ assertRewrite("(a and b) or (a and c)", "a and (b or c)");
+
+
+ assertRewrite("(a or b) and (a or c) and (a or d)", "a or (b and c and d)");
+ assertRewrite("(a and b) or (a and c) or (a and d)", "a and (b or c or d)");
+ assertRewrite("(a and b) or (a or c) or (a and d)", "((((a and b) or a) or c) or (a and d))");
+ assertRewrite("(a and b) or (a and c) or (a or d)", "(((a and b) or (a and c) or a) or d))");
+ assertRewrite("(a or b) or (a and c) or (a and d)", "(a or b) or (a and c) or (a and d)");
+ assertRewrite("(a or b) or (a and c) or (a or d)", "(((a or b) or (a and c)) or d)");
+ assertRewrite("(a or b) or (a or c) or (a and d)", "((a or b) or c) or (a and d)");
+ assertRewrite("(a or b) or (a or c) or (a or d)", "(((a or b) or c) or d)");
+
+ assertRewrite("(a and b) or (d and c) or (d and e)", "(a and b) or (d and c) or (d and e)");
+ assertRewrite("(a or b) and (d or c) and (d or e)", "(a or b) and (d or c) and (d or e)");
+
+ assertRewrite("(a and b) or ((d and c) and (d and e))", "(a and b) or (d and c and e)");
+ assertRewrite("(a or b) and ((d or c) or (d or e))", "(a or b) and (d or c or e)");
+
+ assertRewrite("(a and b) or (a and b and c)", "a and b");
+ assertRewrite("(a or b) and (a or b or c)", "a or b");
+
+ assertRewrite("a and true", "a");
+ assertRewrite("a or false", "a");
+
+ assertRewrite("a and false", "false");
+ assertRewrite("a or true", "true");
+
+ assertRewrite("a or false or false or false", "a");
+ assertRewrite("a and true and true and true", "a");
+
+ assertRewrite("(a and b) or a ", "a");
+ assertRewrite("(a or b) and a ", "a");
+
+ assertRewrite("(a and b) or (a and true)", "a");
+ assertRewrite("(a or b) and (a and true)", "a");
+
+ assertRewrite("(a or b) and (a or true)", "a or b");
+
+ }
+
+ @Test
+ public void testBetweenToCompoundRule() {
+ executor = new ExpressionRuleExecutor(ImmutableList.of(BetweenToCompoundRule.INSTANCE, SimplifyNotExprRule.INSTANCE));
+
+ assertRewrite(" a between c and d", "(a >= c) and (a <= d)");
+ assertRewrite(" a not between c and d)", "(a < c) or (a > d)");
+
+ }
+
private void assertRewrite(String expression, String expected) {
Expression needRewriteExpression = PARSER.parseExpression(expression);
Expression expectedExpression = PARSER.parseExpression(expected);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org