@Override
public PhysicalOperation visitUnion(UnionNode node, LocalExecutionPlanContext context)
{
List<Type> types = getSourceOperatorTypes(node, context.getTypes());
InMemoryExchange inMemoryExchange = new InMemoryExchange(types);
for (int i = 0; i < node.getSources().size(); i++) {
PlanNode subplan = node.getSources().get(i);
List<Symbol> expectedLayout = node.sourceOutputLayout(i);
LocalExecutionPlanContext subContext = context.createSubContext();
PhysicalOperation source = subplan.accept(this, subContext);
List<OperatorFactory> operatorFactories = new ArrayList<>(source.getOperatorFactories());
boolean projectionMatchesOutput = IterableTransformer.on(source.getLayout().entrySet())
.orderBy(Ordering.<Integer>natural().onResultOf(MoreFunctions.<Symbol, Integer>valueGetter()))
.transform(MoreFunctions.<Symbol, Integer>keyGetter())
.list()
.equals(expectedLayout);
if (!projectionMatchesOutput) {
IdentityProjectionInfo mappings = computeIdentityMapping(expectedLayout, source.getLayout(), context.getTypes());
operatorFactories.add(new FilterAndProjectOperator.FilterAndProjectOperatorFactory(
subContext.getNextOperatorId(),
new GenericPageProcessor(FilterFunctions.TRUE_FUNCTION, mappings.getProjections()),
toTypes(mappings.getProjections())));
}
operatorFactories.add(inMemoryExchange.createSinkFactory(subContext.getNextOperatorId()));
DriverFactory driverFactory = new DriverFactory(subContext.isInputDriver(), false, operatorFactories);
context.addDriverFactory(driverFactory);
}
inMemoryExchange.noMoreSinkFactories();
// the main driver is not an input... the union sources are the input for the plan
context.setInputDriver(false);
ImmutableMap.Builder<Symbol, Integer> outputMappings = ImmutableMap.builder();