[enhancement](nereids)add eliminate filter on one row relation rule (#24980)
1.simplify PushdownFilterThroughSetOperation rule 2.add eliminate filter on one row relation rule
This commit is contained in:
@ -198,6 +198,7 @@ public enum RuleType {
|
||||
ELIMINATE_LIMIT_ON_ONE_ROW_RELATION(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_LIMIT_ON_EMPTY_RELATION(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_FILTER(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_FILTER_ON_ONE_RELATION(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_NOT_NULL(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_UNNECESSARY_PROJECT(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_OUTER_JOIN(RuleTypeClass.REWRITE),
|
||||
|
||||
@ -19,27 +19,36 @@ package org.apache.doris.nereids.rules.rewrite;
|
||||
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
|
||||
import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule;
|
||||
import org.apache.doris.nereids.trees.expressions.Alias;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalEmptyRelation;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalOneRowRelation;
|
||||
import org.apache.doris.nereids.util.ExpressionUtils;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Eliminate filter which is FALSE or TRUE.
|
||||
*/
|
||||
public class EliminateFilter extends OneRewriteRuleFactory {
|
||||
public class EliminateFilter implements RewriteRuleFactory {
|
||||
@Override
|
||||
public Rule build() {
|
||||
return logicalFilter()
|
||||
.when(filter -> filter.getConjuncts().stream().anyMatch(BooleanLiteral.class::isInstance))
|
||||
public List<Rule> buildRules() {
|
||||
return ImmutableList.of(logicalFilter().when(
|
||||
filter -> filter.getConjuncts().stream().anyMatch(BooleanLiteral.class::isInstance))
|
||||
.thenApply(ctx -> {
|
||||
LogicalFilter<Plan> filter = ctx.root;
|
||||
Set<Expression> newConjuncts = Sets.newHashSetWithExpectedSize(filter.getConjuncts().size());
|
||||
ImmutableSet.Builder newConjuncts = ImmutableSet.builder();
|
||||
for (Expression expression : filter.getConjuncts()) {
|
||||
if (expression == BooleanLiteral.FALSE) {
|
||||
return new LogicalEmptyRelation(ctx.statementContext.getNextRelationId(),
|
||||
@ -48,12 +57,44 @@ public class EliminateFilter extends OneRewriteRuleFactory {
|
||||
newConjuncts.add(expression);
|
||||
}
|
||||
}
|
||||
if (newConjuncts.isEmpty()) {
|
||||
|
||||
ImmutableSet<Expression> conjuncts = newConjuncts.build();
|
||||
if (conjuncts.isEmpty()) {
|
||||
return filter.child();
|
||||
} else {
|
||||
return new LogicalFilter<>(newConjuncts, filter.child());
|
||||
return new LogicalFilter<>(conjuncts, filter.child());
|
||||
}
|
||||
})
|
||||
.toRule(RuleType.ELIMINATE_FILTER);
|
||||
.toRule(RuleType.ELIMINATE_FILTER),
|
||||
logicalFilter(logicalOneRowRelation()).thenApply(ctx -> {
|
||||
LogicalFilter<LogicalOneRowRelation> filter = ctx.root;
|
||||
Map<Expression, Expression> replaceMap =
|
||||
filter.child().getOutputs().stream().filter(e -> e instanceof Alias)
|
||||
.collect(Collectors.toMap(NamedExpression::toSlot, e -> ((Alias) e).child()));
|
||||
|
||||
ImmutableSet.Builder newConjuncts = ImmutableSet.builder();
|
||||
ExpressionRewriteContext context =
|
||||
new ExpressionRewriteContext(ctx.cascadesContext);
|
||||
for (Expression expression : filter.getConjuncts()) {
|
||||
Expression newExpr = ExpressionUtils.replace(expression, replaceMap);
|
||||
Expression foldExpression =
|
||||
FoldConstantRule.INSTANCE.rewrite(newExpr, context);
|
||||
|
||||
if (foldExpression == BooleanLiteral.FALSE) {
|
||||
return new LogicalEmptyRelation(
|
||||
ctx.statementContext.getNextRelationId(), filter.getOutput());
|
||||
} else if (foldExpression != BooleanLiteral.TRUE) {
|
||||
newConjuncts.add(expression);
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableSet<Expression> conjuncts = newConjuncts.build();
|
||||
if (conjuncts.isEmpty()) {
|
||||
return filter.child();
|
||||
} else {
|
||||
return new LogicalFilter<>(conjuncts, filter.child());
|
||||
}
|
||||
})
|
||||
.toRule(RuleType.ELIMINATE_FILTER_ON_ONE_RELATION));
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,11 +22,8 @@ import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.OneRowRelation;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.SetOperation.Qualifier;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalSetOperation;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalUnion;
|
||||
import org.apache.doris.nereids.util.ExpressionUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@ -44,25 +41,10 @@ public class PushdownFilterThroughSetOperation extends OneRewriteRuleFactory {
|
||||
|
||||
@Override
|
||||
public Rule build() {
|
||||
return logicalFilter(logicalSetOperation()).when(f -> f.child().getQualifier() == Qualifier.ALL).then(f -> {
|
||||
return logicalFilter(logicalSetOperation()).then(f -> {
|
||||
LogicalSetOperation setOperation = f.child();
|
||||
|
||||
if (setOperation instanceof LogicalUnion && ((LogicalUnion) setOperation).hasPushedFilter()) {
|
||||
return f;
|
||||
}
|
||||
|
||||
List<Plan> newChildren = new ArrayList<>();
|
||||
boolean allOneRowRelation = true;
|
||||
boolean hasOneRowRelation = false;
|
||||
for (Plan child : setOperation.children()) {
|
||||
if (child instanceof OneRowRelation) {
|
||||
// We shouldn't push down the 'filter' to 'oneRowRelation'.
|
||||
hasOneRowRelation = true;
|
||||
newChildren.add(child);
|
||||
continue;
|
||||
} else {
|
||||
allOneRowRelation = false;
|
||||
}
|
||||
Map<Expression, Expression> replaceMap = new HashMap<>();
|
||||
for (int i = 0; i < setOperation.getOutputs().size(); ++i) {
|
||||
NamedExpression output = setOperation.getOutputs().get(i);
|
||||
@ -73,14 +55,7 @@ public class PushdownFilterThroughSetOperation extends OneRewriteRuleFactory {
|
||||
ExpressionUtils.replace(conjunct, replaceMap)).collect(ImmutableSet.toImmutableSet());
|
||||
newChildren.add(new LogicalFilter<>(newFilterPredicates, child));
|
||||
}
|
||||
if (allOneRowRelation) {
|
||||
return f;
|
||||
}
|
||||
|
||||
if (hasOneRowRelation) {
|
||||
// If there are some `OneRowRelation` exists, we need to keep the `filter`.
|
||||
return f.withChildren(((LogicalUnion) setOperation).withHasPushedFilter().withChildren(newChildren));
|
||||
}
|
||||
return setOperation.withChildren(newChildren);
|
||||
}).toRule(RuleType.PUSHDOWN_FILTER_THROUGH_SET_OPERATION);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user