[fix](nereids)group by expr may be bound twice in bind agg slot (#28771)
This commit is contained in:
@ -292,10 +292,22 @@ public class BindExpression implements AnalysisRuleFactory {
|
||||
if (alias.child().anyMatch(expr -> expr instanceof AggregateFunction)) {
|
||||
continue;
|
||||
}
|
||||
// NOTICE: must use unbound expressions, because we will bind them in binding group by expr.
|
||||
childOutputsToExpr.putIfAbsent(alias.getName(), agg.getOutputExpressions().get(i).child(0));
|
||||
/*
|
||||
Alias(x) has been bound by binding agg's output
|
||||
we add x to childOutputsToExpr, so when binding group by exprs later, we can use x directly
|
||||
and won't bind it again
|
||||
select
|
||||
p_cycle_time / (select max(p_cycle_time) from log_event_8) as 'x',
|
||||
count(distinct case_id) as 'y'
|
||||
from
|
||||
log_event_8
|
||||
group by
|
||||
x
|
||||
*/
|
||||
childOutputsToExpr.putIfAbsent(alias.getName(), output.get(i).child(0));
|
||||
}
|
||||
|
||||
Set<Expression> boundedGroupByExpressions = Sets.newHashSet();
|
||||
List<Expression> replacedGroupBy = agg.getGroupByExpressions().stream()
|
||||
.map(groupBy -> {
|
||||
if (groupBy instanceof UnboundSlot) {
|
||||
@ -303,7 +315,9 @@ public class BindExpression implements AnalysisRuleFactory {
|
||||
if (unboundSlot.getNameParts().size() == 1) {
|
||||
String name = unboundSlot.getNameParts().get(0);
|
||||
if (childOutputsToExpr.containsKey(name)) {
|
||||
return childOutputsToExpr.get(name);
|
||||
Expression expression = childOutputsToExpr.get(name);
|
||||
boundedGroupByExpressions.add(expression);
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -336,16 +350,24 @@ public class BindExpression implements AnalysisRuleFactory {
|
||||
|
||||
List<Expression> groupBy = replacedGroupBy.stream()
|
||||
.map(expression -> {
|
||||
Expression e = binder.bind(expression);
|
||||
if (e instanceof UnboundSlot) {
|
||||
return childBinder.bind(e);
|
||||
if (boundedGroupByExpressions.contains(expression)) {
|
||||
// expr has been bound by binding agg's output
|
||||
return expression;
|
||||
} else {
|
||||
// bind slot for unbound exprs
|
||||
Expression e = binder.bind(expression);
|
||||
if (e instanceof UnboundSlot) {
|
||||
return childBinder.bind(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
return e;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
groupBy.forEach(expression -> checkBoundExceptLambda(expression, ctx.root));
|
||||
groupBy = groupBy.stream()
|
||||
.map(expr -> bindFunction(expr, ctx.root, ctx.cascadesContext))
|
||||
// bind function for unbound exprs or return old expr if it's bound by binding agg's output
|
||||
.map(expr -> boundedGroupByExpressions.contains(expr) ? expr
|
||||
: bindFunction(expr, ctx.root, ctx.cascadesContext))
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
checkIfOutputAliasNameDuplicatedForGroupBy(groupBy, output);
|
||||
return agg.withGroupByAndOutput(groupBy, output);
|
||||
|
||||
Reference in New Issue
Block a user