IndexHelper<LogicalOperator> indexHelper = new IndexHelper<LogicalOperator>(peers);
Integer foreachPosition = indexHelper.getIndex(foreach);
// Check if flattened fields is required by successor, if so, don't optimize
List<RequiredFields> requiredFieldsList = ((RelationalOperator)successor).getRequiredFields();
RequiredFields requiredFields = requiredFieldsList.get(foreachPosition.intValue());
MultiMap<Integer, Column> foreachMappedFields = foreachProjectionMap.getMappedFields();
if (requiredFields.getFields()!=null) {
for (Pair<Integer, Integer> pair : requiredFields.getFields()) {
Collection<Column> columns = foreachMappedFields.get(pair.second);
if (columns!=null) {
for (Column column : columns) {
Pair<Integer, Integer> foreachInputColumn = column.getInputColumn();
if (foreach.isInputFlattened(foreachInputColumn.second))
return false;
}
}
}
}
// the foreach with flatten can be swapped with an order by
// as the order by will have lesser number of records to sort
// also the sort does not alter the records that are processed
// the foreach with flatten can be pushed down a cross or a join
// for the same reason. In this case the foreach has to be first
// unflattened and then a new foreach has to be inserted after
// the cross or join. In both cross and foreach the actual columns
// from the foreach are not altered but positions might be changed
// in the case of union the column is transformed and as a result
// the foreach flatten cannot be pushed down
// for distinct the output before flattening and the output
// after flattening might be different. For example, consider
// {(1), (1)}. Distinct of this bag is still {(1), (1)}.
// distinct(flatten({(1), (1)})) is (1). However,
// flatten(distinct({(1), (1)})) is (1), (1)
// in both cases correctness is not affected
if(successor instanceof LOSort) {
LOSort sort = (LOSort) successor;
RequiredFields sortRequiredField = sort.getRequiredFields().get(0);
if(sortRequiredField.getNeedAllFields()) {
return false;
}
List<Pair<Integer, Integer>> sortInputs = sortRequiredField.getFields();
Set<Integer> requiredInputs = new HashSet<Integer>();
for(Pair<Integer, Integer> pair: sortInputs) {
requiredInputs.add(pair.second);
}