[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:
@ -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);
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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 """
|
||||
|
||||
Reference in New Issue
Block a user