@Override
public void transform(OperatorPlan matched) throws FrontendException {
subPlan = new OperatorSubPlan(currentPlan);
LOForEach foreach1 = (LOForEach)matched.getSources().get(0);
LOGenerate gen1 = (LOGenerate)foreach1.getInnerPlan().getSinks().get(0);
LOForEach foreach2 = (LOForEach)currentPlan.getSuccessors(foreach1).get(0);
LOGenerate gen2 = (LOGenerate)foreach2.getInnerPlan().getSinks().get(0);
LOForEach newForEach = new LOForEach(currentPlan);
LogicalPlan newForEachInnerPlan = new LogicalPlan();
newForEach.setInnerPlan(newForEachInnerPlan);
newForEach.setAlias(foreach2.getAlias());
newForEach.setRequestedParallelism(foreach1.getRequestedParallelisam());
List<LogicalExpressionPlan> newExpList = new ArrayList<LogicalExpressionPlan>();
LOGenerate newGen = new LOGenerate(newForEachInnerPlan, newExpList, gen2.getFlattenFlags());
newGen.setUserDefinedSchema(gen2.getUserDefinedSchema());
newForEachInnerPlan.add(newGen);
for (LogicalExpressionPlan exp2 : gen2.getOutputPlans()) {
LogicalExpressionPlan newExpPlan = new LogicalExpressionPlan();
LogicalExpressionPlan exp2Copy = exp2.deepCopy();
newExpPlan.merge(exp2Copy);
// Add expression plan in 2nd ForEach
List<Operator> exp2Sinks = new ArrayList<Operator>();
exp2Sinks.addAll(newExpPlan.getSinks());
for (Operator exp2Sink : exp2Sinks) {
if (exp2Sink instanceof ProjectExpression) {
// Find referred expression plan in 1st ForEach
ProjectExpression proj = (ProjectExpression)exp2Sink;
LOInnerLoad innerLoad = (LOInnerLoad)foreach2.getInnerPlan().getPredecessors(gen2).get(proj.getInputNum());
int exp1Pos = innerLoad.getProjection().getColNum();
LogicalExpressionPlan exp1 = gen1.getOutputPlans().get(exp1Pos);
LogicalExpressionPlan exp1Copy = exp1.deepCopy();
List<Operator> exp1Sources = newExpPlan.merge(exp1Copy);
// Copy expression plan to the new ForEach, connect to the expression plan of 2nd ForEach
Operator exp1Source = exp1Sources.get(0);
if (newExpPlan.getPredecessors(exp2Sink)!=null) {
Operator exp2NextToSink = newExpPlan.getPredecessors(exp2Sink).get(0);
Pair<Integer, Integer> pos = newExpPlan.disconnect(exp2NextToSink, exp2Sink);
newExpPlan.remove(exp2Sink);
newExpPlan.connect(exp2NextToSink, pos.first, exp1Source, 0);
}
else {
newExpPlan.remove(exp2Sink);
}
}
}
// Copy referred ForEach1 inner plan to new ForEach
List<Operator> exp1Sinks = newExpPlan.getSinks();
for (Operator exp1Sink : exp1Sinks) {
if (exp1Sink instanceof ProjectExpression) {
Operator opNextToGen = addBranchToPlan(gen1, ((ProjectExpression)exp1Sink).getInputNum(), newForEachInnerPlan, newForEach);
newForEachInnerPlan.connect(opNextToGen, newGen);
int input = newForEachInnerPlan.getPredecessors(newGen).indexOf(opNextToGen);
((ProjectExpression)exp1Sink).setInputNum(input);
}
}
newExpList.add(newExpPlan);
}
// Adjust attachedOp
for (LogicalExpressionPlan p : newGen.getOutputPlans()) {
Iterator<Operator> iter = p.getOperators();
while (iter.hasNext()) {
Operator op = iter.next();
if (op instanceof ProjectExpression) {
((ProjectExpression)op).setAttachedRelationalOp(newGen);