-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat](nereids) support pull up predicate from set operator #39450
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
5d41847
[Feat](nereids) support pull up predicate from set operator
feiniaofeiafei da19001
[Feat](nereids) support pull up predicate from set operator
feiniaofeiafei d15f9f5
fix regression
feiniaofeiafei 12ad38a
[Feat](nereids) support pull up predicate from set operator
feiniaofeiafei 31b32c3
adjust order in rewrite and fix ut
feiniaofeiafei bb3b364
[Feat](nereids) support pull up predicate from set operator
feiniaofeiafei f5c84b9
[Feat](nereids) support pull up predicate from set operator
feiniaofeiafei 91a93cc
fix regression
feiniaofeiafei 4ad57a7
[Feat](nereids) support pull up predicate from set operator
feiniaofeiafei 4859fed
add infer predicate of intersect and except
feiniaofeiafei 497109e
add infer predicate for except and intersect
feiniaofeiafei 78e9b58
use regularChildOutput in setOperation and modify tests
feiniaofeiafei 638198c
remove third infer predicates
feiniaofeiafei bf6c399
fix regression
feiniaofeiafei 2218435
fix regression
feiniaofeiafei 39ee741
remove useless code
feiniaofeiafei 9327850
fix regression
feiniaofeiafei ed7b314
fix regresssion
feiniaofeiafei b74a06a
fix regression
feiniaofeiafei 5a5e271
add comments
feiniaofeiafei a5b7f1b
remove useless code
feiniaofeiafei 1bd2435
support pull up from union with child and const exprs
feiniaofeiafei 8c3e6df
fix ut
feiniaofeiafei 13b6815
fix regression
feiniaofeiafei File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,15 +20,22 @@ | |
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.InPredicate; | ||
import org.apache.doris.nereids.trees.expressions.NamedExpression; | ||
import org.apache.doris.nereids.trees.expressions.Slot; | ||
import org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction; | ||
import org.apache.doris.nereids.trees.expressions.literal.Literal; | ||
import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; | ||
import org.apache.doris.nereids.trees.plans.JoinType; | ||
import org.apache.doris.nereids.trees.plans.Plan; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalExcept; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalFilter; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalIntersect; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalOneRowRelation; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject; | ||
import org.apache.doris.nereids.trees.plans.logical.LogicalUnion; | ||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; | ||
import org.apache.doris.nereids.util.ExpressionUtils; | ||
|
||
|
@@ -38,6 +45,8 @@ | |
import com.google.common.collect.Maps; | ||
import com.google.common.collect.Sets; | ||
|
||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.IdentityHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
@@ -60,6 +69,78 @@ public ImmutableSet<Expression> visit(Plan plan, Void context) { | |
return ImmutableSet.of(); | ||
} | ||
|
||
@Override | ||
public ImmutableSet<Expression> visitLogicalOneRowRelation(LogicalOneRowRelation r, Void context) { | ||
ImmutableSet.Builder<Expression> predicates = ImmutableSet.builder(); | ||
for (NamedExpression expr : r.getProjects()) { | ||
if (expr instanceof Alias && expr.child(0) instanceof Literal) { | ||
predicates.add(new EqualTo(expr.toSlot(), expr.child(0))); | ||
} | ||
} | ||
return predicates.build(); | ||
} | ||
|
||
@Override | ||
public ImmutableSet<Expression> visitLogicalIntersect(LogicalIntersect intersect, Void context) { | ||
return cacheOrElse(intersect, () -> { | ||
ImmutableSet.Builder<Expression> builder = ImmutableSet.builder(); | ||
for (int i = 0; i < intersect.children().size(); ++i) { | ||
Plan child = intersect.child(i); | ||
Set<Expression> childFilters = child.accept(this, context); | ||
if (childFilters.isEmpty()) { | ||
continue; | ||
} | ||
Map<Expression, Expression> replaceMap = new HashMap<>(); | ||
for (int j = 0; j < intersect.getOutput().size(); ++j) { | ||
NamedExpression output = intersect.getOutput().get(j); | ||
replaceMap.put(intersect.getRegularChildOutput(i).get(j), output); | ||
} | ||
builder.addAll(ExpressionUtils.replace(childFilters, replaceMap)); | ||
} | ||
return getAvailableExpressions(builder.build(), intersect); | ||
}); | ||
} | ||
|
||
@Override | ||
public ImmutableSet<Expression> visitLogicalExcept(LogicalExcept except, Void context) { | ||
return cacheOrElse(except, () -> { | ||
if (except.arity() < 1) { | ||
return ImmutableSet.of(); | ||
} | ||
Set<Expression> firstChildFilters = except.child(0).accept(this, context); | ||
if (firstChildFilters.isEmpty()) { | ||
return ImmutableSet.of(); | ||
} | ||
Map<Expression, Expression> replaceMap = new HashMap<>(); | ||
for (int i = 0; i < except.getOutput().size(); ++i) { | ||
NamedExpression output = except.getOutput().get(i); | ||
replaceMap.put(except.getRegularChildOutput(0).get(i), output); | ||
} | ||
return ImmutableSet.copyOf(ExpressionUtils.replace(firstChildFilters, replaceMap)); | ||
}); | ||
} | ||
|
||
@Override | ||
public ImmutableSet<Expression> visitLogicalUnion(LogicalUnion union, Void context) { | ||
return cacheOrElse(union, () -> { | ||
if (!union.getConstantExprsList().isEmpty() && union.arity() == 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why could not process union with both constantExprs and normal children? how about
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
return getFiltersFromUnionConstExprs(union); | ||
} else if (union.getConstantExprsList().isEmpty() && union.arity() != 0) { | ||
return getFiltersFromUnionChild(union, context); | ||
} else if (!union.getConstantExprsList().isEmpty() && union.arity() != 0) { | ||
HashSet<Expression> fromChildFilters = new HashSet<>(getFiltersFromUnionChild(union, context)); | ||
if (fromChildFilters.isEmpty()) { | ||
return ImmutableSet.of(); | ||
} | ||
if (!ExpressionUtils.unionConstExprsSatisfyConjuncts(union, fromChildFilters)) { | ||
return ImmutableSet.of(); | ||
} | ||
return ImmutableSet.copyOf(fromChildFilters); | ||
} | ||
return ImmutableSet.of(); | ||
}); | ||
} | ||
|
||
@Override | ||
public ImmutableSet<Expression> visitLogicalFilter(LogicalFilter<? extends Plan> filter, Void context) { | ||
return cacheOrElse(filter, () -> { | ||
|
@@ -77,6 +158,10 @@ public ImmutableSet<Expression> visitLogicalJoin(LogicalJoin<? extends Plan, ? e | |
ImmutableSet<Expression> rightPredicates = join.right().accept(this, context); | ||
predicates.addAll(leftPredicates); | ||
predicates.addAll(rightPredicates); | ||
if (join.getJoinType() == JoinType.CROSS_JOIN || join.getJoinType() == JoinType.INNER_JOIN) { | ||
predicates.addAll(join.getHashJoinConjuncts()); | ||
predicates.addAll(join.getOtherJoinConjuncts()); | ||
} | ||
return getAvailableExpressions(predicates, join); | ||
}); | ||
} | ||
|
@@ -138,6 +223,9 @@ private ImmutableSet<Expression> cacheOrElse(Plan plan, Supplier<ImmutableSet<Ex | |
} | ||
|
||
private ImmutableSet<Expression> getAvailableExpressions(Set<Expression> predicates, Plan plan) { | ||
if (predicates.isEmpty()) { | ||
return ImmutableSet.of(); | ||
} | ||
Set<Expression> inferPredicates = PredicatePropagation.infer(predicates); | ||
Builder<Expression> newPredicates = ImmutableSet.builderWithExpectedSize(predicates.size() + 10); | ||
Set<Slot> outputSet = plan.getOutputSet(); | ||
|
@@ -159,4 +247,55 @@ private ImmutableSet<Expression> getAvailableExpressions(Set<Expression> predica | |
private boolean hasAgg(Expression expression) { | ||
return expression.anyMatch(AggregateFunction.class::isInstance); | ||
} | ||
|
||
private ImmutableSet<Expression> getFiltersFromUnionChild(LogicalUnion union, Void context) { | ||
Set<Expression> filters = new HashSet<>(); | ||
for (int i = 0; i < union.getArity(); ++i) { | ||
Plan child = union.child(i); | ||
Set<Expression> childFilters = child.accept(this, context); | ||
if (childFilters.isEmpty()) { | ||
return ImmutableSet.of(); | ||
} | ||
Map<Expression, Expression> replaceMap = new HashMap<>(); | ||
for (int j = 0; j < union.getOutput().size(); ++j) { | ||
NamedExpression output = union.getOutput().get(j); | ||
replaceMap.put(union.getRegularChildOutput(i).get(j), output); | ||
} | ||
Set<Expression> unionFilters = ExpressionUtils.replace(childFilters, replaceMap); | ||
if (0 == i) { | ||
filters.addAll(unionFilters); | ||
} else { | ||
filters.retainAll(unionFilters); | ||
} | ||
if (filters.isEmpty()) { | ||
return ImmutableSet.of(); | ||
} | ||
} | ||
return ImmutableSet.copyOf(filters); | ||
} | ||
|
||
private ImmutableSet<Expression> getFiltersFromUnionConstExprs(LogicalUnion union) { | ||
List<List<NamedExpression>> constExprs = union.getConstantExprsList(); | ||
ImmutableSet.Builder<Expression> filtersFromConstExprs = ImmutableSet.builder(); | ||
for (int col = 0; col < union.getOutput().size(); ++col) { | ||
Expression compareExpr = union.getOutput().get(col); | ||
Set<Expression> options = new HashSet<>(); | ||
for (List<NamedExpression> constExpr : constExprs) { | ||
if (constExpr.get(col) instanceof Alias | ||
&& ((Alias) constExpr.get(col)).child() instanceof Literal) { | ||
options.add(((Alias) constExpr.get(col)).child()); | ||
} else { | ||
options.clear(); | ||
break; | ||
} | ||
} | ||
options.removeIf(option -> option instanceof NullLiteral); | ||
if (options.size() > 1) { | ||
filtersFromConstExprs.add(new InPredicate(compareExpr, options)); | ||
} else if (options.size() == 1) { | ||
filtersFromConstExprs.add(new EqualTo(compareExpr, options.iterator().next())); | ||
} | ||
} | ||
return filtersFromConstExprs.build(); | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comments to explain why move this rewrite topic here