[fix](nereids) having with no group by is not parsed correctly (#14883)

SQL: SELECT * FROM tbl HAVING c1 > 10;
This commit is contained in:
starocean999
2022-12-12 22:03:37 +08:00
committed by GitHub
parent e57419fc9e
commit 281d47434a
6 changed files with 89 additions and 9 deletions

View File

@ -1076,11 +1076,29 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
// from -> where -> group by -> having -> select
LogicalPlan filter = withFilter(inputRelation, whereClause);
SelectColumnClauseContext columnCtx = selectClause.selectColumnClause();
LogicalPlan aggregate = withAggregate(filter, columnCtx, aggClause);
SelectColumnClauseContext selectColumnCtx = selectClause.selectColumnClause();
LogicalPlan aggregate = withAggregate(filter, selectColumnCtx, aggClause);
// TODO: replace and process having at this position
LogicalPlan having = withHaving(aggregate, havingClause);
return withProjection(having, selectClause.selectColumnClause(), aggClause);
if (!(aggregate instanceof Aggregate) && havingClause.isPresent()) {
// create a project node for pattern match of ProjectToGlobalAggregate rule
// then ProjectToGlobalAggregate rule can insert agg node as LogicalHaving node's child
LogicalPlan project;
if (selectColumnCtx.EXCEPT() != null) {
List<NamedExpression> expressions = getNamedExpressions(selectColumnCtx.namedExpressionSeq());
if (!expressions.stream().allMatch(UnboundSlot.class::isInstance)) {
throw new ParseException("only column name is supported in except clause", selectColumnCtx);
}
project = new LogicalProject<>(ImmutableList.of(new UnboundStar(Collections.emptyList())),
expressions, aggregate);
} else {
List<NamedExpression> projects = getNamedExpressions(selectColumnCtx.namedExpressionSeq());
project = new LogicalProject<>(projects, Collections.emptyList(), aggregate);
}
return new LogicalHaving<>(getExpression((havingClause.get().booleanExpression())), project);
} else {
LogicalPlan having = withHaving(aggregate, havingClause);
return withProjection(having, selectColumnCtx, aggClause);
}
});
}

View File

@ -54,6 +54,7 @@ public enum RuleType {
REPLACE_SORT_EXPRESSION_BY_CHILD_OUTPUT(RuleTypeClass.REWRITE),
FILL_UP_HAVING_AGGREGATE(RuleTypeClass.REWRITE),
FILL_UP_HAVING_PROJECT(RuleTypeClass.REWRITE),
FILL_UP_SORT_AGGREGATE(RuleTypeClass.REWRITE),
FILL_UP_SORT_HAVING_AGGREGATE(RuleTypeClass.REWRITE),
FILL_UP_SORT_PROJECT(RuleTypeClass.REWRITE),

View File

@ -246,12 +246,12 @@ public class BindSlotReference implements AnalysisRuleFactory {
})
),
RuleType.BINDING_HAVING_SLOT.build(
logicalHaving(aggregate()).when(Plan::canBind).thenApply(ctx -> {
LogicalHaving<Aggregate<GroupPlan>> having = ctx.root;
Aggregate<GroupPlan> aggregate = having.child();
logicalHaving(any()).when(Plan::canBind).thenApply(ctx -> {
LogicalHaving<Plan> having = ctx.root;
Plan childPlan = having.child();
// We should deduplicate the slots, otherwise the binding process will fail due to the
// ambiguous slots exist.
Set<Slot> boundSlots = Stream.concat(Stream.of(aggregate), aggregate.children().stream())
Set<Slot> boundSlots = Stream.concat(Stream.of(childPlan), childPlan.children().stream())
.flatMap(plan -> plan.getOutput().stream())
.collect(Collectors.toSet());
Expression boundPredicates = new SlotBinder(

View File

@ -120,7 +120,10 @@ public class FillUpMissingSlots implements AnalysisRuleFactory {
having.getPredicates(), r.getSubstitution());
return new LogicalFilter<>(newPredicates, a);
});
})
})),
RuleType.FILL_UP_HAVING_PROJECT.build(
logicalHaving(logicalProject()).then(having -> new LogicalFilter<>(having.getPredicates(),
having.child()))
)
);
}

View File

@ -54,3 +54,49 @@
2
3
-- !select --
9
-- !select --
1
1
1
2
2
2
3
3
3
-- !select --
1
1
1
2
2
2
3
3
3
-- !select --
36
-- !select --
36
-- !select --
36
-- !select --
36
-- !select --
54
-- !select --
54
-- !select --
9

View File

@ -18,6 +18,7 @@
suite("test_nereids_having") {
sql "SET enable_nereids_planner=true"
sql "SET enable_fallback_to_original_planner=true"
sql "SET enable_vectorized_engine=true"
sql "DROP TABLE IF EXISTS test_nereids_having_tbl"
@ -57,4 +58,15 @@ suite("test_nereids_having") {
order_qt_select "SELECT a1, SUM(a1 + a2) FROM test_nereids_having_tbl GROUP BY a1 HAVING SUM(a1 + a2) > 0";
order_qt_select "SELECT a1, SUM(a1 + a2) FROM test_nereids_having_tbl GROUP BY a1 HAVING SUM(a1 + a2 + 3) > 0";
order_qt_select "SELECT a1 FROM test_nereids_having_tbl GROUP BY a1 HAVING COUNT(*) > 0";
order_qt_select "SELECT COUNT(*) FROM test_nereids_having_tbl HAVING COUNT(*) > 0";
order_qt_select "SELECT a1 as value FROM test_nereids_having_tbl HAVING a1 > 0";
order_qt_select "SELECT a1 as value FROM test_nereids_having_tbl HAVING value > 0";
order_qt_select "SELECT SUM(a2) FROM test_nereids_having_tbl HAVING SUM(a2) > 0";
order_qt_select "SELECT SUM(a2) as value FROM test_nereids_having_tbl HAVING SUM(a2) > 0";
order_qt_select "SELECT SUM(a2) as value FROM test_nereids_having_tbl HAVING value > 0";
order_qt_select "SELECT SUM(a2) FROM test_nereids_having_tbl HAVING MIN(pk) > 0";
order_qt_select "SELECT SUM(a1 + a2) FROM test_nereids_having_tbl HAVING SUM(a1 + a2) > 0";
order_qt_select "SELECT SUM(a1 + a2) FROM test_nereids_having_tbl HAVING SUM(a1 + a2 + 3) > 0";
order_qt_select "SELECT COUNT(*) FROM test_nereids_having_tbl HAVING COUNT(*) > 0";
}