[fix](Nereids) make agg output unchanged after normalized (#23499)
The normalizedAgg rule can change the output of agg. For example: ``` select c1 as c, c1 from t having c1 > 0 ``` The normalizedAgg rule will make a plan with output c, which can cause the having filter error Therefore, the output exprId should be unchanged after normalized
This commit is contained in:
@ -33,6 +33,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
import org.apache.doris.nereids.util.ExpressionUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
@ -185,24 +186,6 @@ public class NormalizeAggregate extends OneRewriteRuleFactory implements Normali
|
||||
bottomProjects.addAll(aggInputSlots);
|
||||
// build group by exprs
|
||||
List<Expression> normalizedGroupExprs = groupByToSlotContext.normalizeToUseSlotRef(groupingByExprs);
|
||||
// build upper project, use two context to do pop up, because agg output maybe contain two part:
|
||||
// group by keys and agg expressions
|
||||
List<NamedExpression> upperProjects = groupByToSlotContext
|
||||
.normalizeToUseSlotRefWithoutWindowFunction(aggregateOutput);
|
||||
upperProjects = normalizedAggFuncsToSlotContext.normalizeToUseSlotRefWithoutWindowFunction(upperProjects);
|
||||
// process Expression like Alias(SlotReference#0)#0
|
||||
upperProjects = upperProjects.stream().map(e -> {
|
||||
if (e instanceof Alias) {
|
||||
Alias alias = (Alias) e;
|
||||
if (alias.child() instanceof SlotReference) {
|
||||
SlotReference slotReference = (SlotReference) alias.child();
|
||||
if (slotReference.getExprId().equals(alias.getExprId())) {
|
||||
return slotReference;
|
||||
}
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
Plan bottomPlan;
|
||||
if (!bottomProjects.isEmpty()) {
|
||||
@ -211,11 +194,41 @@ public class NormalizeAggregate extends OneRewriteRuleFactory implements Normali
|
||||
bottomPlan = aggregate.child();
|
||||
}
|
||||
|
||||
List<NamedExpression> upperProjects = normalizeOutput(aggregateOutput,
|
||||
groupByToSlotContext, normalizedAggFuncsToSlotContext);
|
||||
|
||||
return new LogicalProject<>(upperProjects,
|
||||
aggregate.withNormalized(normalizedGroupExprs, normalizedAggOutput, bottomPlan));
|
||||
}).toRule(RuleType.NORMALIZE_AGGREGATE);
|
||||
}
|
||||
|
||||
private List<NamedExpression> normalizeOutput(List<NamedExpression> aggregateOutput,
|
||||
NormalizeToSlotContext groupByToSlotContext, NormalizeToSlotContext normalizedAggFuncsToSlotContext) {
|
||||
// build upper project, use two context to do pop up, because agg output maybe contain two part:
|
||||
// group by keys and agg expressions
|
||||
List<NamedExpression> upperProjects = groupByToSlotContext
|
||||
.normalizeToUseSlotRefWithoutWindowFunction(aggregateOutput);
|
||||
upperProjects = normalizedAggFuncsToSlotContext.normalizeToUseSlotRefWithoutWindowFunction(upperProjects);
|
||||
|
||||
Builder<NamedExpression> builder = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < aggregateOutput.size(); i++) {
|
||||
NamedExpression e = upperProjects.get(i);
|
||||
// process Expression like Alias(SlotReference#0)#0
|
||||
if (e instanceof Alias && e.child(0) instanceof SlotReference) {
|
||||
SlotReference slotReference = (SlotReference) e.child(0);
|
||||
if (slotReference.getExprId().equals(e.getExprId())) {
|
||||
e = slotReference;
|
||||
}
|
||||
}
|
||||
// Make the output ExprId unchanged
|
||||
if (!e.getExprId().equals(aggregateOutput.get(i).getExprId())) {
|
||||
e = new Alias(aggregateOutput.get(i).getExprId(), e, aggregateOutput.get(i).getName());
|
||||
}
|
||||
builder.add(e);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static class CollectNonWindowedAggFuncs extends DefaultExpressionVisitor<Void, List<AggregateFunction>> {
|
||||
|
||||
private static final CollectNonWindowedAggFuncs INSTANCE = new CollectNonWindowedAggFuncs();
|
||||
|
||||
@ -91,7 +91,16 @@ public class CaseWhen extends Expression {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toSql();
|
||||
StringBuilder output = new StringBuilder("CASE");
|
||||
for (Expression child : children()) {
|
||||
if (child instanceof WhenClause) {
|
||||
output.append(child);
|
||||
} else {
|
||||
output.append(" ELSE ").append(child.toString());
|
||||
}
|
||||
}
|
||||
output.append(" END");
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -111,6 +111,6 @@ public class WhenClause extends Expression implements BinaryExpression, ExpectsI
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toSql();
|
||||
return " WHEN " + left().toString() + " THEN " + right().toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user