morrySnow commented on code in PR #14490: URL: https://github.com/apache/doris/pull/14490#discussion_r1030575257
########## fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java: ########## @@ -845,33 +851,43 @@ public PlanFragment visitPhysicalProject(PhysicalProject<? extends Plan> project } } PlanFragment inputFragment = project.child(0).accept(this, context); - List<Expr> execExprList = project.getProjects() .stream() .map(e -> ExpressionTranslator.translate(e, context)) .collect(Collectors.toList()); // TODO: fix the project alias of an aliased relation. - List<Slot> slotList = project.getOutput(); - TupleDescriptor tupleDescriptor = generateTupleDesc(slotList, null, context); + PlanNode inputPlanNode = inputFragment.getPlanRoot(); - // For hash join node, use vSrcToOutputSMap to describe the expression calculation, use - // vIntermediateTupleDescList as input, and set vOutputTupleDesc as the final output. - // TODO: HashJoinNode's be implementation is not support projection yet, remove this after when supported. - if (inputPlanNode instanceof HashJoinNode) { - HashJoinNode hashJoinNode = (HashJoinNode) inputPlanNode; - hashJoinNode.setvOutputTupleDesc(tupleDescriptor); - hashJoinNode.setvSrcToOutputSMap(execExprList); - return inputFragment; - } - if (inputPlanNode instanceof NestedLoopJoinNode) { - NestedLoopJoinNode nestedLoopJoinNode = (NestedLoopJoinNode) inputPlanNode; - nestedLoopJoinNode.setvOutputTupleDesc(tupleDescriptor); - nestedLoopJoinNode.setvSrcToOutputSMap(execExprList); - return inputFragment; + if (isUnnecessaryProject(project)) { + List<NamedExpression> namedExpressions = project.getProjects(); + for (NamedExpression n : namedExpressions) { + for (Expression e : n.children()) { + SlotRef slotRef = context.findSlotRef(((SlotReference) e).getExprId()); + SlotReference slotReference = (SlotReference) e; + context.addExprIdSlotRefPair(slotReference.getExprId(), slotRef); + } + } + } else { + List<Slot> slotList = project.getOutput(); + TupleDescriptor tupleDescriptor = generateTupleDesc(slotList, null, context); + inputPlanNode.setProjectList(execExprList); + inputPlanNode.setOutputTupleDesc(tupleDescriptor); + // For hash join node, use vSrcToOutputSMap to describe the expression calculation, use + // vIntermediateTupleDescList as input, and set vOutputTupleDesc as the final output. + // TODO: HashJoinNode's be implementation is not support projection yet, remove this after when supported. + if (inputPlanNode instanceof HashJoinNode) { + HashJoinNode hashJoinNode = (HashJoinNode) inputPlanNode; + hashJoinNode.setvOutputTupleDesc(tupleDescriptor); + hashJoinNode.setvSrcToOutputSMap(execExprList); + return inputFragment; + } + if (inputPlanNode instanceof NestedLoopJoinNode) { + NestedLoopJoinNode nestedLoopJoinNode = (NestedLoopJoinNode) inputPlanNode; + nestedLoopJoinNode.setvOutputTupleDesc(tupleDescriptor); + nestedLoopJoinNode.setvSrcToOutputSMap(execExprList); + return inputFragment; Review Comment: project on join node cannot be remove, this is a constraint on BE ########## fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java: ########## @@ -128,6 +128,12 @@ public PlanFragment translatePlan(PhysicalPlan physicalPlan, PlanTranslatorConte rootFragment = exchangeToMergeFragment(rootFragment, context); } List<Expr> outputExprs = Lists.newArrayList(); + if (physicalPlan instanceof PhysicalProject) { + PhysicalProject project = (PhysicalProject) physicalPlan; + if (isUnnecessaryProject(project)) { + physicalPlan = (PhysicalPlan) physicalPlan.child(0); + } + } Review Comment: after remove the root project node, we should set output exprs's order as them in the project to ensure the result is correct. ########## fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java: ########## @@ -1162,4 +1178,19 @@ private PlanFragment constructShuffleJoin(AbstractPhysicalJoin<PhysicalPlan, Phy return joinFragment; } + + private boolean isUnnecessaryProject(PhysicalProject project) { + List<NamedExpression> projects = project.getProjects(); + for (NamedExpression p : projects) { + if (p.children().size() > 1) { + return false; + } + for (Expression e : p.children()) { + if (!(e instanceof SlotReference)) { + return false; + } + } + } Review Comment: ``` 1. project.output.size == project.child.output.size 2. project.output.allMatch(expr -> expr instance of SlotReference || (expr instance Alias && expr.child instance of SlotReference)) ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org