Code review comment: when we add multiLayerProjection, we do not modify its original projects. That is why only translator need to be modified.

Code before review:
public PlanFragment visitPhysicalProject(PhysicalProject<? extends Plan> project, PlanTranslatorContext context) {
if (project.child(0) instanceof AbstractPhysicalJoin) {
((AbstractPhysicalJoin<?, ?>) project.child(0)).setShouldTranslateOutput(false);
}
if (project.child(0) instanceof PhysicalFilter) {
if (project.child(0).child(0) instanceof AbstractPhysicalJoin) {
((AbstractPhysicalJoin<?, ?>) project.child(0).child(0)).setShouldTranslateOutput(false);
}
}
PlanFragment inputFragment = project.child(0).accept(this, context);
if (inputFragment.getPlanRoot() instanceof OlapScanNode) {
registerRewrittenSlot(project, (OlapScanNode) inputFragment.getPlanRoot());
}
PlanNode inputPlanNode = inputFragment.getPlanRoot();
List<Expr> projectionExprs = null;
List<Expr> allProjectionExprs = Lists.newArrayList();
List<Slot> slots = null;
if (project.hasMultiLayerProjection() && !(inputFragment instanceof MultiCastPlanFragment)) {
int layerCount = project.getMultiLayerProjects().size();
for (int i = 0; i < layerCount; i++) {
List<NamedExpression> layer = project.getMultiLayerProjects().get(i);
projectionExprs = layer.stream()
.map(e -> ExpressionTranslator.translate(e, context))
.collect(Collectors.toList());
slots = layer.stream()
.map(NamedExpression::toSlot)
.collect(Collectors.toList());
if (i < layerCount - 1) {
inputPlanNode.addIntermediateProjectList(projectionExprs);
TupleDescriptor projectionTuple = generateTupleDesc(slots, null, context);
inputPlanNode.addIntermediateOutputTupleDescList(projectionTuple);
}
allProjectionExprs.addAll(projectionExprs);
}
} else {
projectionExprs = project.getProjects()
.stream()
.map(e -> ExpressionTranslator.translate(e, context))
.collect(Collectors.toList());
slots = project.getProjects()
.stream()
.map(NamedExpression::toSlot)
.collect(Collectors.toList());
allProjectionExprs.addAll(projectionExprs);
}
if (inputFragment instanceof MultiCastPlanFragment) {
MultiCastDataSink multiCastDataSink = (MultiCastDataSink) inputFragment.getSink();
DataStreamSink dataStreamSink = multiCastDataSink.getDataStreamSinks().get(
multiCastDataSink.getDataStreamSinks().size() - 1);
TupleDescriptor projectionTuple = generateTupleDesc(slots, null, context);
dataStreamSink.setProjections(projectionExprs);
dataStreamSink.setOutputTupleDesc(projectionTuple);
return inputFragment;
}
List<Expr> conjuncts = inputPlanNode.getConjuncts();
Set<SlotId> requiredSlotIdSet = Sets.newHashSet();
for (Expr expr : allProjectionExprs) {
Expr.extractSlots(expr, requiredSlotIdSet);
}
Set<SlotId> requiredByProjectSlotIdSet = Sets.newHashSet(requiredSlotIdSet);
for (Expr expr : conjuncts) {
Expr.extractSlots(expr, requiredSlotIdSet);
}
if (inputPlanNode instanceof JoinNodeBase) {
TupleDescriptor tupleDescriptor = generateTupleDesc(slots, null, context);
JoinNodeBase joinNode = (JoinNodeBase) inputPlanNode;
joinNode.setOutputTupleDesc(tupleDescriptor);
joinNode.setProjectList(projectionExprs);
if (joinNode instanceof HashJoinNode) {
((HashJoinNode) joinNode).getHashOutputSlotIds().clear();
Set<ExprId> requiredExprIds = Sets.newHashSet();
Set<SlotId> requiredOtherConjunctsSlotIdSet = Sets.newHashSet();
List<Expr> otherConjuncts = ((HashJoinNode) joinNode).getOtherJoinConjuncts();
for (Expr expr : otherConjuncts) {
Expr.extractSlots(expr, requiredOtherConjunctsSlotIdSet);
}
if (!((HashJoinNode) joinNode).getEqJoinConjuncts().isEmpty()
&& !((HashJoinNode) joinNode).getMarkJoinConjuncts().isEmpty()) {
List<Expr> markConjuncts = ((HashJoinNode) joinNode).getMarkJoinConjuncts();
for (Expr expr : markConjuncts) {
Expr.extractSlots(expr, requiredOtherConjunctsSlotIdSet);
}
}
requiredOtherConjunctsSlotIdSet.forEach(e -> requiredExprIds.add(context.findExprId(e)));
requiredSlotIdSet.forEach(e -> requiredExprIds.add(context.findExprId(e)));
for (ExprId exprId : requiredExprIds) {
SlotId slotId = ((HashJoinNode) joinNode).getHashOutputExprSlotIdMap().get(exprId);
if (slotId != null) {
((HashJoinNode) joinNode).addSlotIdToHashOutputSlotIds(slotId);
}
}
}
return inputFragment;
}
if (inputPlanNode instanceof TableFunctionNode) {
TableFunctionNode tableFunctionNode = (TableFunctionNode) inputPlanNode;
tableFunctionNode.setOutputSlotIds(Lists.newArrayList(requiredSlotIdSet));
}
if (inputPlanNode instanceof ScanNode) {
TupleDescriptor projectionTuple = null;
List<SlotId> slotIdsByOrder = Lists.newArrayList();
if (requiredByProjectSlotIdSet.size() != requiredSlotIdSet.size()
|| new HashSet<>(projectionExprs).size() != projectionExprs.size()
|| projectionExprs.stream().anyMatch(expr -> !(expr instanceof SlotRef))) {
projectionTuple = generateTupleDesc(slots,
((ScanNode) inputPlanNode).getTupleDesc().getTable(), context);
inputPlanNode.setProjectList(projectionExprs);
inputPlanNode.setOutputTupleDesc(projectionTuple);
} else {
for (int i = 0; i < slots.size(); ++i) {
context.addExprIdSlotRefPair(slots.get(i).getExprId(),
(SlotRef) projectionExprs.get(i));
slotIdsByOrder.add(((SlotRef) projectionExprs.get(i)).getSlotId());
}
}
if (inputPlanNode instanceof OlapScanNode) {
ArrayList<SlotDescriptor> olapScanSlots =
context.getTupleDesc(inputPlanNode.getTupleIds().get(0)).getSlots();
SlotDescriptor lastSlot = olapScanSlots.get(olapScanSlots.size() - 1);
if (lastSlot.getColumn() != null
&& lastSlot.getColumn().getName().equals(Column.ROWID_COL)) {
if (projectionTuple != null) {
injectRowIdColumnSlot(projectionTuple);
SlotRef slotRef = new SlotRef(lastSlot);
inputPlanNode.getProjectList().add(slotRef);
requiredByProjectSlotIdSet.add(lastSlot.getId());
} else {
slotIdsByOrder.add(lastSlot.getId());
}
requiredSlotIdSet.add(lastSlot.getId());
}
}
updateScanSlotsMaterialization((ScanNode) inputPlanNode, requiredSlotIdSet,
requiredByProjectSlotIdSet, slotIdsByOrder, context);
} else {
TupleDescriptor tupleDescriptor = generateTupleDesc(slots, null, context);
inputPlanNode.setProjectList(projectionExprs);
inputPlanNode.setOutputTupleDesc(tupleDescriptor);
}
return inputFragment;
}

Line under review: if (project.hasMultiLayerProjection() && !(inputFragment instanceof MultiCastPlanFragment)) {

Code after addressing the review:
public PlanFragment visitPhysicalProject(PhysicalProject<? extends Plan> project, PlanTranslatorContext context) {
if (project.child(0) instanceof AbstractPhysicalJoin) {
((AbstractPhysicalJoin<?, ?>) project.child(0)).setShouldTranslateOutput(false);
}
if (project.child(0) instanceof PhysicalFilter) {
if (project.child(0).child(0) instanceof AbstractPhysicalJoin) {
((AbstractPhysicalJoin<?, ?>) project.child(0).child(0)).setShouldTranslateOutput(false);
}
}
PlanFragment inputFragment = project.child(0).accept(this, context);
if (inputFragment.getPlanRoot() instanceof OlapScanNode) {
registerRewrittenSlot(project, (OlapScanNode) inputFragment.getPlanRoot());
}
PlanNode inputPlanNode = inputFragment.getPlanRoot();
List<Expr> projectionExprs = null;
List<Expr> allProjectionExprs = Lists.newArrayList();
List<Slot> slots = null;
if (project.hasMultiLayerProjection() && !(inputFragment instanceof MultiCastPlanFragment)) {
int layerCount = project.getMultiLayerProjects().size();
for (int i = 0; i < layerCount; i++) {
List<NamedExpression> layer = project.getMultiLayerProjects().get(i);
projectionExprs = layer.stream()
.map(e -> ExpressionTranslator.translate(e, context))
.collect(Collectors.toList());
slots = layer.stream()
.map(NamedExpression::toSlot)
.collect(Collectors.toList());
if (i < layerCount - 1) {
inputPlanNode.addIntermediateProjectList(projectionExprs);
TupleDescriptor projectionTuple = generateTupleDesc(slots, null, context);
inputPlanNode.addIntermediateOutputTupleDescList(projectionTuple);
}
allProjectionExprs.addAll(projectionExprs);
}
} else {
projectionExprs = project.getProjects()
.stream()
.map(e -> ExpressionTranslator.translate(e, context))
.collect(Collectors.toList());
slots = project.getProjects()
.stream()
.map(NamedExpression::toSlot)
.collect(Collectors.toList());
allProjectionExprs.addAll(projectionExprs);
}
if (inputFragment instanceof MultiCastPlanFragment) {
MultiCastDataSink multiCastDataSink = (MultiCastDataSink) inputFragment.getSink();
DataStreamSink dataStreamSink = multiCastDataSink.getDataStreamSinks().get(
multiCastDataSink.getDataStreamSinks().size() - 1);
TupleDescriptor projectionTuple = generateTupleDesc(slots, null, context);
dataStreamSink.setProjections(projectionExprs);
dataStreamSink.setOutputTupleDesc(projectionTuple);
return inputFragment;
}
List<Expr> conjuncts = inputPlanNode.getConjuncts();
Set<SlotId> requiredSlotIdSet = Sets.newHashSet();
for (Expr expr : allProjectionExprs) {
Expr.extractSlots(expr, requiredSlotIdSet);
}
Set<SlotId> requiredByProjectSlotIdSet = Sets.newHashSet(requiredSlotIdSet);
for (Expr expr : conjuncts) {
Expr.extractSlots(expr, requiredSlotIdSet);
}
if (inputPlanNode instanceof JoinNodeBase) {
TupleDescriptor tupleDescriptor = generateTupleDesc(slots, null, context);
JoinNodeBase joinNode = (JoinNodeBase) inputPlanNode;
joinNode.setOutputTupleDesc(tupleDescriptor);
joinNode.setProjectList(projectionExprs);
if (joinNode instanceof HashJoinNode) {
((HashJoinNode) joinNode).getHashOutputSlotIds().clear();
Set<ExprId> requiredExprIds = Sets.newHashSet();
Set<SlotId> requiredOtherConjunctsSlotIdSet = Sets.newHashSet();
List<Expr> otherConjuncts = ((HashJoinNode) joinNode).getOtherJoinConjuncts();
for (Expr expr : otherConjuncts) {
Expr.extractSlots(expr, requiredOtherConjunctsSlotIdSet);
}
if (!((HashJoinNode) joinNode).getEqJoinConjuncts().isEmpty()
&& !((HashJoinNode) joinNode).getMarkJoinConjuncts().isEmpty()) {
List<Expr> markConjuncts = ((HashJoinNode) joinNode).getMarkJoinConjuncts();
for (Expr expr : markConjuncts) {
Expr.extractSlots(expr, requiredOtherConjunctsSlotIdSet);
}
}
requiredOtherConjunctsSlotIdSet.forEach(e -> requiredExprIds.add(context.findExprId(e)));
requiredSlotIdSet.forEach(e -> requiredExprIds.add(context.findExprId(e)));
for (ExprId exprId : requiredExprIds) {
SlotId slotId = ((HashJoinNode) joinNode).getHashOutputExprSlotIdMap().get(exprId);
if (slotId != null) {
((HashJoinNode) joinNode).addSlotIdToHashOutputSlotIds(slotId);
}
}
}
return inputFragment;
}
if (inputPlanNode instanceof TableFunctionNode) {
TableFunctionNode tableFunctionNode = (TableFunctionNode) inputPlanNode;
tableFunctionNode.setOutputSlotIds(Lists.newArrayList(requiredSlotIdSet));
}
if (inputPlanNode instanceof ScanNode) {
TupleDescriptor projectionTuple = null;
List<SlotId> slotIdsByOrder = Lists.newArrayList();
if (requiredByProjectSlotIdSet.size() != requiredSlotIdSet.size()
|| new HashSet<>(projectionExprs).size() != projectionExprs.size()
|| projectionExprs.stream().anyMatch(expr -> !(expr instanceof SlotRef))) {
projectionTuple = generateTupleDesc(slots,
((ScanNode) inputPlanNode).getTupleDesc().getTable(), context);
inputPlanNode.setProjectList(projectionExprs);
inputPlanNode.setOutputTupleDesc(projectionTuple);
} else {
for (int i = 0; i < slots.size(); ++i) {
context.addExprIdSlotRefPair(slots.get(i).getExprId(),
(SlotRef) projectionExprs.get(i));
slotIdsByOrder.add(((SlotRef) projectionExprs.get(i)).getSlotId());
}
}
if (inputPlanNode instanceof OlapScanNode) {
ArrayList<SlotDescriptor> olapScanSlots =
context.getTupleDesc(inputPlanNode.getTupleIds().get(0)).getSlots();
SlotDescriptor lastSlot = olapScanSlots.get(olapScanSlots.size() - 1);
if (lastSlot.getColumn() != null
&& lastSlot.getColumn().getName().equals(Column.ROWID_COL)) {
if (projectionTuple != null) {
injectRowIdColumnSlot(projectionTuple);
SlotRef slotRef = new SlotRef(lastSlot);
inputPlanNode.getProjectList().add(slotRef);
requiredByProjectSlotIdSet.add(lastSlot.getId());
} else {
slotIdsByOrder.add(lastSlot.getId());
}
requiredSlotIdSet.add(lastSlot.getId());
}
}
updateScanSlotsMaterialization((ScanNode) inputPlanNode, requiredSlotIdSet,
requiredByProjectSlotIdSet, slotIdsByOrder, context);
} else {
TupleDescriptor tupleDescriptor = generateTupleDesc(slots, null, context);
inputPlanNode.setProjectList(projectionExprs);
inputPlanNode.setOutputTupleDesc(tupleDescriptor);
}
return inputFragment;
}