public PlanContext createExecPlan(PlanContext planContext) {
RecordSource leftSrc = getLeft();
RecordSource rightSrc = getRight();
// Create separate execution plans to gather data from our upstream sources.
PlanContext leftContext = getSubPlan(leftSrc, planContext);
PlanContext rightContext = getSubPlan(rightSrc, planContext);
// Add our upstream source plans to our graph.
FlowSpecification flowSpec = planContext.getFlowSpec();
flowSpec.addNodesFromDAG(leftContext.getFlowSpec());
flowSpec.addNodesFromDAG(rightContext.getFlowSpec());
// Get the true field names that represent keys on the left and right
// sides of the join.
String leftName = leftSrc.getSourceName();
AssignedSymbol leftSym = (AssignedSymbol) getLeftKey().resolveAliases();
TypedField leftKey = new TypedField(leftSym.getAssignedName(), leftSym.getType());
String rightName = rightSrc.getSourceName();
AssignedSymbol rightSym = (AssignedSymbol) getRightKey().resolveAliases();
TypedField rightKey = new TypedField(rightSym.getAssignedName(), rightSym.getType());
WindowSpec window = null;
try {
// This should evaluate to itself, but make sure to resolve it anyway.
assert mWindowExpr.isConstant();
window = (WindowSpec) mWindowExpr.eval(new EmptyEventWrapper());
} catch (IOException ioe) {
// mWindowExpr should be constant, so this should be impossible.
LOG.error("IOException calculating window expression: " + ioe);
// Signal error by returning a null flow specification anyway.
planContext.setFlowSpec(null);
return planContext;
}
HashJoinNode joinNode = new HashJoinNode(leftName, rightName, leftKey, rightKey,
window, getSourceName(), leftContext.getOutFields(), rightContext.getOutFields(),
planContext.getConf());
// Set this node to expect multiple input schemas.
List<Schema> inputSchemas = new ArrayList<Schema>();
inputSchemas.add(leftContext.getSchema());
inputSchemas.add(rightContext.getSchema());
joinNode.setAttr(PlanNode.MULTI_INPUT_SCHEMA_ATTR, inputSchemas);
flowSpec.attachToLastLayer(joinNode);
// Create an output context defining our fields, etc.
PlanContext outContext = new PlanContext(planContext);
SymbolTable outTable = SymbolTable.mergeSymbols(leftContext.getSymbolTable(),
rightContext.getSymbolTable(), planContext.getSymbolTable());
outContext.setSymbolTable(outTable);
List<TypedField> outputFields = new ArrayList<TypedField>();
outputFields.addAll(leftContext.getOutFields());
outputFields.addAll(rightContext.getOutFields());
outputFields = distinctFields(outputFields);
outContext.setOutFields(outputFields);
Schema outSchema = createFieldSchema(outputFields);
outContext.setSchema(outSchema);
joinNode.setAttr(PlanNode.OUTPUT_SCHEMA_ATTR, outSchema);
return outContext;
}