This is an automated email from the ASF dual-hosted git repository.
huajianlan pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.0 by this push:
new bd7446244dd [fix](Nereids) fix bind having aggregate failed again
(#33148)
bd7446244dd is described below
commit bd7446244ddc521ef67faa4bd502fdf6f0a61338
Author: 924060929 <[email protected]>
AuthorDate: Tue Apr 2 21:58:15 2024 +0800
[fix](Nereids) fix bind having aggregate failed again (#33148)
cherry from #32490 and #32687
---
.../nereids/rules/analysis/BindExpression.java | 83 ++++++++++++++++++----
.../doris/nereids/rules/analysis/SlotBinder.java | 11 +++
.../data/nereids_syntax_p0/bind_priority.out | 23 ++++++
.../suites/nereids_syntax_p0/bind_priority.groovy | 80 +++++++++++++++++++++
4 files changed, 185 insertions(+), 12 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
index aa44674cf98..e0f0d1baa78 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
@@ -497,21 +497,75 @@ public class BindExpression implements
AnalysisRuleFactory {
}
}
List<Slot> groupBySlots = groupBySlotsBuilder.build();
+ SlotBinder bindByGroupBy = new
SlotBinder(toScope(ctx.cascadesContext, groupBySlots),
+ ctx.cascadesContext, false, false, true
+ );
+ Scope aggOuputScope = toScope(ctx.cascadesContext,
childPlan.getOutput());
+ SlotBinder bindByAggOutput = new SlotBinder(
+ aggOuputScope,
+ ctx.cascadesContext, false, true, true
+ );
+ SlotBinder bindByAggChild = new SlotBinder(
+ toScope(ctx.cascadesContext,
childPlan.child().getOutput()),
+ ctx.cascadesContext, false, true, true
+ );
+
+ SubExprAnalyzer bindSlot = new SubExprAnalyzer(
+ aggOuputScope, ctx.cascadesContext) {
+ private boolean currentIsInAggregateFunction;
+
+ @Override
+ public Expression visitAggregateFunction(
+ AggregateFunction aggregateFunction,
CascadesContext context) {
+ if (!currentIsInAggregateFunction) {
+ currentIsInAggregateFunction = true;
+ try {
+ return
super.visitAggregateFunction(aggregateFunction, context);
+ } finally {
+ currentIsInAggregateFunction = false;
+ }
+ } else {
+ return
super.visitAggregateFunction(aggregateFunction, context);
+ }
+ }
- Set<Expression> boundConjuncts =
having.getConjuncts().stream()
- .map(expr -> {
- if (hasAggregateFunction(expr,
functionRegistry)) {
- expr = bindSlot(expr, childPlan.child(),
ctx.cascadesContext, false);
- } else {
- expr = new
SlotBinder(toScope(ctx.cascadesContext, groupBySlots),
- ctx.cascadesContext, false, false
- ).bind(expr);
+ @Override
+ public Expression visitUnboundFunction(
+ UnboundFunction unboundFunction,
CascadesContext context) {
+ if (!currentIsInAggregateFunction
+ && isAggregateFunction(unboundFunction,
functionRegistry)) {
+ currentIsInAggregateFunction = true;
+ try {
+ return
super.visitUnboundFunction(unboundFunction, context);
+ } finally {
+ currentIsInAggregateFunction = false;
+ }
+ } else {
+ return
super.visitUnboundFunction(unboundFunction, context);
+ }
+ }
- expr = bindSlot(expr, childPlan,
ctx.cascadesContext, false);
- expr = bindSlot(expr,
childPlan.children(), ctx.cascadesContext, false);
+ @Override
+ public Expression visitUnboundSlot(UnboundSlot
unboundSlot, CascadesContext context) {
+ if (currentIsInAggregateFunction) {
+ // bind by agg child
+ return bindSlot(unboundSlot,
childPlan.child(), ctx.cascadesContext, false);
+ } else {
+ Expression expr =
bindByGroupBy.bind(unboundSlot);
+ if (expr instanceof SlotReference) {
+ return expr;
}
- return expr;
- })
+ expr = bindByAggOutput.bind(expr);
+ if (expr instanceof SlotReference) {
+ return expr;
+ }
+ return bindByAggChild.bind(expr);
+ }
+ }
+ };
+
+ Set<Expression> boundConjuncts =
having.getConjuncts().stream()
+ .map(slot -> slot.accept(bindSlot, null))
.map(expr -> bindFunction(expr, ctx.root,
ctx.cascadesContext))
.map(expr ->
TypeCoercionUtils.castIfNotSameType(expr, BooleanType.INSTANCE))
.collect(Collectors.toSet());
@@ -847,6 +901,11 @@ public class BindExpression implements AnalysisRuleFactory
{
return expression;
}
+ private boolean isAggregateFunction(UnboundFunction unboundFunction,
FunctionRegistry functionRegistry) {
+ return functionRegistry.isAggregateFunction(
+ unboundFunction.getDbName(), unboundFunction.getName());
+ }
+
private boolean hasAggregateFunction(Expression expression,
FunctionRegistry functionRegistry) {
return expression.anyMatch(expr -> {
if (expr instanceof AggregateFunction) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
index 99d55423689..e1cbb7760c4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
@@ -69,6 +69,7 @@ public class SlotBinder extends SubExprAnalyzer {
*/
private final boolean enableExactMatch;
private final boolean bindSlotInOuterScope;
+ private final boolean findFirst;
public SlotBinder(Scope scope, CascadesContext cascadesContext) {
this(scope, cascadesContext, true, true);
@@ -76,9 +77,16 @@ public class SlotBinder extends SubExprAnalyzer {
public SlotBinder(Scope scope, CascadesContext cascadesContext,
boolean enableExactMatch, boolean bindSlotInOuterScope) {
+ this(scope, cascadesContext, enableExactMatch, bindSlotInOuterScope,
false);
+ }
+
+ public SlotBinder(Scope scope, CascadesContext cascadesContext,
+ boolean enableExactMatch, boolean bindSlotInOuterScope,
+ boolean findFirst) {
super(scope, cascadesContext);
this.enableExactMatch = enableExactMatch;
this.bindSlotInOuterScope = bindSlotInOuterScope;
+ this.findFirst = findFirst;
}
public Expression bind(Expression expression) {
@@ -169,6 +177,9 @@ public class SlotBinder extends SubExprAnalyzer {
return exactMatch.get(0);
}
}
+ if (findFirst) {
+ return bounded.get(0);
+ }
throw new AnalysisException(String.format("%s is ambiguous:
%s.",
unboundSlot.toSql(),
bounded.stream()
diff --git a/regression-test/data/nereids_syntax_p0/bind_priority.out
b/regression-test/data/nereids_syntax_p0/bind_priority.out
index b3bc666c23d..32619942eed 100644
--- a/regression-test/data/nereids_syntax_p0/bind_priority.out
+++ b/regression-test/data/nereids_syntax_p0/bind_priority.out
@@ -61,3 +61,26 @@ all 2
-- !having_bind_child5 --
2 11
+-- !having_bind_agg_fun --
+
+-- !having_bind_agg_fun --
+2 4
+3 3
+
+-- !having_bind_group_by --
+7 3
+
+-- !having_bind_group_by --
+7 3
+
+-- !having_bind_group_by --
+7 3
+
+-- !having_bind_group_by --
+4 5 3
+
+-- !having_bind_group_by --
+1 2
+
+-- !having_bind_group_by --
+2 1
diff --git a/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
b/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
index 0e02f01a18b..c60cce38678 100644
--- a/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
+++ b/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
@@ -229,5 +229,85 @@ suite("bind_priority") {
group by id
having sum(age + 1) = 11 -- bind age from s
"""
+
+
+
+
+ sql "drop table if exists test_bind_having_slots2"
+ sql """create table test_bind_having_slots2
+ (id int)
+ distributed by hash(id)
+ properties('replication_num'='1');
+ """
+ sql "insert into test_bind_having_slots2 values(1), (2), (3), (2);"
+
+ order_qt_having_bind_agg_fun """
+ select id, abs(sum(id)) as id
+ from test_bind_having_slots2
+ group by id
+ having sum(id) + id >= 7
+ """
+
+ order_qt_having_bind_agg_fun """
+ select id, abs(sum(id)) as id
+ from test_bind_having_slots2
+ group by id
+ having sum(id) + id >= 6
+ """
+
+
+
+
+
+ sql "drop table if exists test_bind_having_slots3"
+
+ sql """CREATE TABLE `test_bind_having_slots3`(pk int, pk2 int)
+ DUPLICATE KEY(`pk`)
+ DISTRIBUTED BY HASH(`pk`) BUCKETS 10
+ properties('replication_num'='1');
+ """
+ sql "insert into test_bind_having_slots3 values(1, 1), (2, 2), (2, 2),
(3, 3), (3, 3), (3, 3);"
+
+ order_qt_having_bind_group_by """
+ SELECT pk + 6 as ps, COUNT(pk ) * 3 as pk
+ FROM test_bind_having_slots3 tbl_alias1
+ GROUP by pk
+ HAVING pk = 1
+ """
+
+ order_qt_having_bind_group_by """
+ SELECT pk + 6 as pk, COUNT(pk ) * 3 as pk
+ FROM test_bind_having_slots3 tbl_alias1
+ GROUP by pk + 6
+ HAVING pk = 7
+ """
+
+ order_qt_having_bind_group_by """
+ SELECT pk + 6, COUNT(pk ) * 3 as pk
+ FROM test_bind_having_slots3 tbl_alias1
+ GROUP by pk + 6
+ HAVING pk = 3
+ """
+
+ order_qt_having_bind_group_by """
+ select pk + 1 as pk, pk + 2 as pk, count(*)
+ from test_bind_having_slots3
+ group by pk + 1, pk + 2
+ having pk = 4;
+ """
+
+ order_qt_having_bind_group_by """
+ select count(*) pk, pk + 1 as pk
+ from test_bind_having_slots3
+ group by pk + 1, pk + 2
+ having pk = 1;
+ """
+
+ order_qt_having_bind_group_by """
+ select pk + 1 as pk, count(*) pk
+ from test_bind_having_slots3
+ group by pk + 1, pk + 2
+ having pk = 2;
+ """
}()
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]