diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Project.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Project.java index 9724d0e8cad169..0f1b80b0cb383f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Project.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/algebra/Project.java @@ -23,8 +23,6 @@ import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.Slot; -import org.apache.doris.nereids.trees.expressions.SlotReference; -import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -73,16 +71,26 @@ default Map getAliasToProducer() { * @return project list for merged project */ default List mergeProjections(Project childProject) { - List thisProjectExpressions = getProjects(); - List childProjectExpressions = childProject.getProjects(); - Map bottomAliasMap = childProjectExpressions.stream() + Map replaceMap = childProject.getProjects().stream() .filter(e -> e instanceof Alias) .collect(Collectors.toMap( - NamedExpression::toSlot, e -> e) - ); - return thisProjectExpressions.stream() - .map(e -> ExpressionReplacer.INSTANCE.replace(e, bottomAliasMap)) - .map(NamedExpression.class::cast) + NamedExpression::toSlot, + e -> (Alias) e)); + return getProjects().stream() + .map(expr -> { + if (expr instanceof Alias) { + Alias alias = (Alias) expr; + Expression insideExpr = alias.child(); + Expression newInsideExpr = insideExpr.rewriteUp(e -> { + Alias getAlias = replaceMap.get(e); + return getAlias == null ? e : getAlias.child(); + }); + return newInsideExpr == insideExpr ? expr : alias.withChildren(ImmutableList.of(newInsideExpr)); + } else { + Alias getAlias = replaceMap.get(expr); + return getAlias == null ? expr : getAlias; + } + }) .collect(ImmutableList.toImmutableList()); } @@ -106,71 +114,6 @@ static List findProject( }) .collect(ImmutableList.toImmutableList()); } - - /** - * findUsedProject. if not found the slot, then skip it - */ - static List filterUsedOutputs( - Collection slotReferences, List childOutput) { - Map exprIdToChildOutput = childOutput.stream() - .collect(ImmutableMap.toImmutableMap(p -> p.getExprId(), p -> p)); - - return slotReferences.stream() - .map(slot -> exprIdToChildOutput.get(slot.getExprId())) - .filter(project -> project != null) - .collect(ImmutableList.toImmutableList()); - } - - /** - * replace alias - */ - public static class ExpressionReplacer extends DefaultExpressionRewriter> { - public static final ExpressionReplacer INSTANCE = new ExpressionReplacer(); - - public Expression replace(Expression expr, Map substitutionMap) { - if (expr instanceof SlotReference) { - Slot ref = ((SlotReference) expr).withQualifier(ImmutableList.of()); - return substitutionMap.getOrDefault(ref, expr); - } - return visit(expr, substitutionMap); - } - - /** - * case 1: - * project(alias(c) as d, alias(x) as y) - * | - * | ===> project(alias(a) as d, alias(b) as y) - * | - * project(slotRef(a) as c, slotRef(b) as x) - * case 2: - * project(slotRef(x.c), slotRef(x.d)) - * | ===> project(slotRef(a) as x.c, slotRef(b) as x.d) - * project(slotRef(a) as c, slotRef(b) as d) - * case 3: others - */ - @Override - public Expression visit(Expression expr, Map substitutionMap) { - if (expr instanceof Alias && expr.child(0) instanceof SlotReference) { - // case 1: - Expression c = expr.child(0); - // Alias doesn't contain qualifier - Slot ref = ((SlotReference) c).withQualifier(ImmutableList.of()); - if (substitutionMap.containsKey(ref)) { - return expr.withChildren(substitutionMap.get(ref).children()); - } - } else if (expr instanceof SlotReference) { - // case 2: - Slot ref = ((SlotReference) expr).withQualifier(ImmutableList.of()); - if (substitutionMap.containsKey(ref)) { - Alias res = (Alias) substitutionMap.get(ref); - return res.child(); - } - } else if (substitutionMap.containsKey(expr)) { - return substitutionMap.get(expr).child(0); - } - return super.visit(expr, substitutionMap); - } - } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/MergeProjectsTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/MergeProjectsTest.java index 4c04874a06ca6b..4ec9d82fa719da 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/MergeProjectsTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/MergeProjectsTest.java @@ -87,7 +87,8 @@ public void testMergeConsecutiveProjectsWithAlias() { @Test void testAlias() { - // project(a+1 as b) -> project(b+1 as c) + // project(b+1 as c) + // -> project(a+1 as b) LogicalProject bottomProject = new LogicalProject<>( ImmutableList.of(new Alias(new Add(score.getOutput().get(0), Literal.of(1)), "b")), score); LogicalProject> topProject = new LogicalProject<>(