Set<Long> input = (Set<Long>)foreach.getAnnotation(ColumnPruneHelper.INPUTUIDS);
LogicalRelationalOperator op = (LogicalRelationalOperator)foreach.getPlan().getPredecessors(foreach).get(0);
Set<Integer> cols = columnHelper.getColumns(op.getSchema(), input);
LogicalPlan innerPlan = foreach.getInnerPlan();
LOGenerate gen = (LOGenerate)innerPlan.getSinks().get(0);
// clean up the predecessors of LOGenerate
List<Operator> ll = innerPlan.getPredecessors(gen);
List<Operator> toRemove = new ArrayList<Operator>();
for(int i=0; i<ll.size(); i++) {
// if the LOInnerLoads for this subplan are all in the column set,
// no change required, keep going
if (checkInnerLoads((LogicalRelationalOperator)ll.get(i), cols)) {
continue;
}
// clean up and adjust expression plans
Iterator<LogicalExpressionPlan> iter = gen.getOutputPlans().iterator();
int j=-1;
while(iter.hasNext()) {
j++;
LogicalExpressionPlan exp = iter.next();
List<Operator> sinks = exp.getSinks();
for(Operator s: sinks) {
if (s instanceof ProjectExpression) {
int inputNo = ((ProjectExpression)s).getInputNum();
if (inputNo + toRemove.size() == i) {
// if this expression has this input that is to be removed,
// then remove this expression plan
iter.remove();
// adjust flatten flags
boolean[] flatten = gen.getFlattenFlags();
for(int k=j; k<flatten.length-1; k++) {
flatten[k] = flatten[k+1];
}
break;
} else if (inputNo + toRemove.size() > i) {
// adjust input number for all projections whose
// input number is after the one to be removed
((ProjectExpression)s).setInputNum(inputNo-1);
}
}
}
}
// this LOInnerLoad and its successors should be removed, add to the remove list
toRemove.add(ll.get(i));
}
for(Operator pred: toRemove) {
removeSubTree((LogicalRelationalOperator)pred);
}
// trim the flatten flags in case some expressions are removed
boolean[] flatten = new boolean[gen.getOutputPlans().size()];
System.arraycopy(gen.getFlattenFlags(), 0, flatten, 0, flatten.length);
gen.setFlattenFlags(flatten);
}