@Override
public void transform(OperatorPlan matched) throws FrontendException {
subPlan = new OperatorSubPlan( currentPlan );
LOForEach foreach = (LOForEach)matched.getSources().get(0);
Operator next = currentPlan.getSuccessors( foreach ).get(0);
if( next instanceof LOSort ) {
Operator pred = currentPlan.getPredecessors( foreach ).get( 0 );
List<Operator> succs = new ArrayList<Operator>();
succs.addAll(currentPlan.getSuccessors( next ));
Pair<Integer, Integer> pos1 = currentPlan.disconnect( pred, foreach );
Pair<Integer, Integer> pos2 = currentPlan.disconnect( foreach, next );
currentPlan.connect( pred, pos1.first, next, pos2.second );
if( succs != null ) {
for( Operator succ : succs ) {
Pair<Integer, Integer> pos = currentPlan.disconnect( next, succ );
currentPlan.connect( next, pos.first, foreach, 0 );
currentPlan.connect( foreach, 0, succ, pos.second );
}
} else {
currentPlan.connect( next, foreach );
}
subPlan.add(foreach);
subPlan.add(next);
} else if( next instanceof LOCross || next instanceof LOJoin ) {
List<Operator> preds = currentPlan.getPredecessors( next );
List<Integer> fieldsToBeFlattaned = new ArrayList<Integer>();
Map<Integer, LogicalSchema> cachedUserDefinedSchema = new HashMap<Integer, LogicalSchema>();
boolean[] flags = null;
int fieldCount = 0;
for( Operator op : preds ) {
if( op == foreach ) {
LOGenerate gen = OptimizerUtils.findGenerate( foreach );
flags = gen.getFlattenFlags();
for( int i = 0; i < flags.length; i++ ) {
if( flags[i] ) {
fieldsToBeFlattaned.add(fieldCount);
if (gen.getUserDefinedSchema()!=null && gen.getUserDefinedSchema().get(i)!=null) {
cachedUserDefinedSchema.put(fieldCount, gen.getUserDefinedSchema().get(i));
gen.getUserDefinedSchema().set(i, null);
}
fieldCount++;
} else {
fieldCount++;
}
}
} else {
fieldCount += ( (LogicalRelationalOperator)op ).getSchema().size();
}
}
boolean[] flattenFlags = new boolean[fieldCount];
List<LogicalSchema> mUserDefinedSchema = null;
if (cachedUserDefinedSchema!=null) {
mUserDefinedSchema = new ArrayList<LogicalSchema>();
for (int i=0;i<fieldCount;i++)
mUserDefinedSchema.add(null);
}
for( Integer i : fieldsToBeFlattaned ) {
flattenFlags[i] = true;
if (cachedUserDefinedSchema.containsKey(i)) {
mUserDefinedSchema.set(i, cachedUserDefinedSchema.get(i));
}
}
// Now create a new foreach after cross/join and insert it into the plan.
LOForEach newForeach = new LOForEach( currentPlan );
LogicalPlan innerPlan = new LogicalPlan();
List<LogicalExpressionPlan> exprs = new ArrayList<LogicalExpressionPlan>( fieldCount );
LOGenerate gen = new LOGenerate( innerPlan, exprs, flattenFlags );
if (mUserDefinedSchema!=null)
gen.setUserDefinedSchema(mUserDefinedSchema);
innerPlan.add( gen );
newForeach.setInnerPlan( innerPlan );
for( int i = 0; i < fieldCount; i++ ) {
LogicalExpressionPlan expr = new LogicalExpressionPlan();
expr.add( new ProjectExpression( expr, i, -1, gen ) );
exprs.add( expr );
LOInnerLoad innerLoad = new LOInnerLoad(innerPlan, newForeach, i);
innerPlan.add(innerLoad);
innerPlan.connect(innerLoad, gen);
}
newForeach.setAlias(((LogicalRelationalOperator)next).getAlias());
Operator opAfterX = null;
List<Operator> succs = currentPlan.getSuccessors( next );
if( succs == null || succs.size() == 0 ) {
currentPlan.add( newForeach );