}
@Override
public boolean check(List<LogicalOperator> nodes) throws OptimizerException {
try {
LOForEach foreach = (LOForEach) getOperator(nodes);
Pair<Boolean, List<Integer>> flattenResult = foreach.hasFlatten();
boolean flattened = flattenResult.first;
List<Integer> flattenedColumns = flattenResult.second;
Set<Integer> flattenedColumnSet = (flattenedColumns == null? null: new HashSet<Integer>(flattenedColumns));
if(!flattened) {
return false;
}
if(flattenedColumns == null || flattenedColumns.size() == 0) {
return false;
}
ProjectionMap foreachProjectionMap = foreach.getProjectionMap();
if(foreachProjectionMap == null) {
return false;
}
List<Integer> foreachAddedFields = foreachProjectionMap.getAddedFields();
if(foreachAddedFields != null) {
Set<Integer> foreachAddedFieldsSet = new HashSet<Integer>(foreachAddedFields);
flattenedColumnSet.removeAll(foreachAddedFieldsSet);
}
if(flattenedColumnSet.size() == 0) {
return false;
}
for(LogicalPlan foreachPlan: foreach.getForEachPlans()) {
UDFFinder udfFinder = new UDFFinder(foreachPlan);
udfFinder.visit();
// if any of the foreach's inner plans contain a UDF then return false
if (udfFinder.foundAnyUDF()) {
return false;
}
CastFinder castFinder = new CastFinder(foreachPlan);
castFinder.visit();
// TODO
// if any of the foreach's inner plans contain a cast then return false
// in the future the cast should be moved appropriately
if (castFinder.foundAnyCast()) {
return false;
}
}
List<LogicalOperator> successors = (mPlan.getSuccessors(foreach) == null ? null
: new ArrayList<LogicalOperator>(mPlan
.getSuccessors(foreach)));
// if the foreach has no successors or more than one successor
// return false
if (successors == null || successors.size() == 0 || successors.size() > 1) {
return false;
}
LogicalOperator successor = successors.get(0);
List<LogicalOperator> peers = (mPlan.getPredecessors(successor) == null ? null
: new ArrayList<LogicalOperator>(mPlan.getPredecessors(successor)));
// check if any of the foreach's peers is a foreach flatten
// if so then this rule does not apply
if (peers != null){
for(LogicalOperator peer: peers) {
if(!peer.equals(foreach)) {
if(peer instanceof LOForEach) {
LOForEach peerForeach = (LOForEach)peer;
if(peerForeach.hasFlatten().first) {
return false;
}
}
}
}