[fix](Nereids): fill miss slot in having subquery (#27177)

fill miss slot in having subquery.

such as 
```
select * from t group by k having max(k) in (select k from t2)
```

the max(k) should be push down aggregate
This commit is contained in:
谢健
2023-11-21 18:54:58 +08:00
committed by GitHub
parent 6fb57c2e1a
commit 445484270b
3 changed files with 27 additions and 5 deletions

View File

@ -21,11 +21,13 @@ import org.apache.doris.nereids.CascadesContext;
import org.apache.doris.nereids.StatementContext;
import org.apache.doris.nereids.rules.Rule;
import org.apache.doris.nereids.rules.RuleType;
import org.apache.doris.nereids.trees.TreeNode;
import org.apache.doris.nereids.trees.expressions.Alias;
import org.apache.doris.nereids.trees.expressions.BinaryOperator;
import org.apache.doris.nereids.trees.expressions.Exists;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.InSubquery;
import org.apache.doris.nereids.trees.expressions.ListQuery;
import org.apache.doris.nereids.trees.expressions.MarkJoinSlotReference;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
import org.apache.doris.nereids.trees.expressions.Or;
@ -73,7 +75,7 @@ public class SubqueryToApply implements AnalysisRuleFactory {
LogicalFilter<Plan> filter = ctx.root;
ImmutableList<Set<SubqueryExpr>> subqueryExprsList = filter.getConjuncts().stream()
.<Set<SubqueryExpr>>map(e -> e.collect(SubqueryExpr.class::isInstance))
.<Set<SubqueryExpr>>map(e -> e.collect(SubqueryToApply::canConvertToSupply))
.collect(ImmutableList.toImmutableList());
if (subqueryExprsList.stream()
.flatMap(Collection::stream).noneMatch(SubqueryExpr.class::isInstance)) {
@ -122,7 +124,7 @@ public class SubqueryToApply implements AnalysisRuleFactory {
RuleType.PROJECT_SUBQUERY_TO_APPLY.build(logicalProject().thenApply(ctx -> {
LogicalProject<Plan> project = ctx.root;
ImmutableList<Set<SubqueryExpr>> subqueryExprsList = project.getProjects().stream()
.<Set<SubqueryExpr>>map(e -> e.collect(SubqueryExpr.class::isInstance))
.<Set<SubqueryExpr>>map(e -> e.collect(SubqueryToApply::canConvertToSupply))
.collect(ImmutableList.toImmutableList());
if (subqueryExprsList.stream().flatMap(Collection::stream).count() == 0) {
return project;
@ -191,7 +193,7 @@ public class SubqueryToApply implements AnalysisRuleFactory {
}
ImmutableList<Set<SubqueryExpr>> subqueryExprsList = subqueryConjuncts.stream()
.<Set<SubqueryExpr>>map(e -> e.collect(SubqueryExpr.class::isInstance))
.<Set<SubqueryExpr>>map(e -> e.collect(SubqueryToApply::canConvertToSupply))
.collect(ImmutableList.toImmutableList());
ImmutableList.Builder<Expression> newConjuncts = new ImmutableList.Builder<>();
LogicalPlan applyPlan;
@ -235,10 +237,17 @@ public class SubqueryToApply implements AnalysisRuleFactory {
);
}
private static boolean canConvertToSupply(TreeNode<Expression> expression) {
// The subquery except ListQuery can be converted to Supply
return expression instanceof SubqueryExpr && !(expression instanceof ListQuery);
}
private static boolean isValidSubqueryConjunct(Expression expression) {
// only support 1 subquery expr in the expression
// don't support expression like subquery1 or subquery2
return expression.collectToList(SubqueryExpr.class::isInstance).size() == 1;
return expression
.collectToList(SubqueryToApply::canConvertToSupply)
.size() == 1;
}
private enum RelatedInfo {
@ -264,7 +273,7 @@ public class SubqueryToApply implements AnalysisRuleFactory {
Set<Slot> rightOutputSlots = rightChild.getOutputSet();
for (int i = 0; i < size; ++i) {
Expression expression = subqueryConjuncts.get(i);
List<SubqueryExpr> subqueryExprs = expression.collectToList(SubqueryExpr.class::isInstance);
List<SubqueryExpr> subqueryExprs = expression.collectToList(SubqueryToApply::canConvertToSupply);
RelatedInfo relatedInfo = RelatedInfo.UnSupported;
if (subqueryExprs.size() == 1) {
SubqueryExpr subqueryExpr = subqueryExprs.get(0);

View File

@ -23,6 +23,7 @@ import org.apache.doris.nereids.types.BooleanType;
import org.apache.doris.nereids.types.DataType;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Objects;
@ -107,6 +108,11 @@ public class InSubquery extends SubqueryExpr {
return new InSubquery(children.get(0), (ListQuery) children.get(1), isNot);
}
@Override
public List<Expression> children() {
return Lists.newArrayList(compareExpr, listQuery);
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {

View File

@ -52,6 +52,13 @@ suite("test_subquery") {
select * from nereids_test_query_db.baseall where k1 = (select k1 from nereids_test_query_db.baseall limit 1)
"""
// test uncorrelated subquery in having
sql """
select count(*) from nereids_test_query_db.baseall
group by k0
having min(k0) in (select k0 from nereids_test_query_db.baseall)
"""
// test uncorrelated scalar subquery with more than one return rows
test {
sql """