// keys[i] -> ArrayList<exprNodeDesc> for the i-th join operator key list
ArrayList<ArrayList<ExprNodeDesc>> keys = new ArrayList<ArrayList<ExprNodeDesc>>();
int keyLength = 0;
for (int i = 0; i < right.length; i++) {
Operator oi = (i == 0 && right[i] == null ? left : right[i]);
ReduceSinkDesc now = ((ReduceSinkOperator) (oi)).getConf();
if (i == 0) {
keyLength = now.getKeyCols().size();
} else {
assert (keyLength == now.getKeyCols().size());
}
keys.add(now.getKeyCols());
}
// implicit type conversion hierarchy
for (int k = 0; k < keyLength; k++) {
// Find the common class for type conversion
TypeInfo commonType = keys.get(0).get(k).getTypeInfo();
for (int i = 1; i < right.length; i++) {
TypeInfo a = commonType;
TypeInfo b = keys.get(i).get(k).getTypeInfo();
commonType = FunctionRegistry.getCommonClassForComparison(a, b);
if (commonType == null) {
throw new SemanticException(
"Cannot do equality join on different types: " + a.getTypeName()
+ " and " + b.getTypeName());
}
}
// Add implicit type conversion if necessary
for (int i = 0; i < right.length; i++) {
if (TypeInfoUtils.isConversionRequiredForComparison(
keys.get(i).get(k).getTypeInfo(),
commonType)) {
keys.get(i).set(
k,
ParseUtils.createConversionCast(
keys.get(i).get(k), (PrimitiveTypeInfo)commonType));
}
}
}
// regenerate keySerializationInfo because the ReduceSinkOperator's
// output key types might have changed.
for (int i = 0; i < right.length; i++) {
Operator oi = (i == 0 && right[i] == null ? left : right[i]);
ReduceSinkDesc now = ((ReduceSinkOperator) (oi)).getConf();
now.setKeySerializeInfo(PlanUtils.getReduceKeyTableDesc(PlanUtils
.getFieldSchemasFromColumnList(now.getKeyCols(), "joinkey"), now
.getOrder()));
}
}