@Override
public void transform(List<LogicalOperator> nodes) throws OptimizerException {
try {
LogicalOperator lo = getOperator(nodes);
Schema s = lo.getSchema();
String scope = lo.getOperatorKey().scope;
// For every field, build a logical plan. If the field has a type
// other than byte array, then the plan will be cast(project). Else
// it will just be project.
ArrayList<LogicalPlan> genPlans = new ArrayList<LogicalPlan>(s.size());
ArrayList<Boolean> flattens = new ArrayList<Boolean>(s.size());
Map<String, Byte> typeChanges = new HashMap<String, Byte>();
// if we are inserting casts in a load and if the loader
// implements determineSchema(), insert casts only where necessary
// Note that in this case, the data coming out of the loader is not
// a BYTEARRAY but is whatever determineSchema() says it is.
Schema determinedSchema = null;
if(LOLoad.class.getName().equals(operatorClassName)) {
determinedSchema = ((LOLoad)lo).getDeterminedSchema();
}
for (int i = 0; i < s.size(); i++) {
LogicalPlan p = new LogicalPlan();
genPlans.add(p);
flattens.add(false);
List<Integer> toProject = new ArrayList<Integer>(1);
toProject.add(i);
LOProject proj = new LOProject(p, OperatorKey.genOpKey(scope),
lo, toProject);
p.add(proj);
Schema.FieldSchema fs = s.getField(i);
if (fs.type != DataType.BYTEARRAY) {
if(determinedSchema == null || (fs.type != determinedSchema.getField(i).type)) {
// Either no schema was determined by loader OR the type
// from the "determinedSchema" is different
// from the type specified - so we need to cast
LOCast cast = new LOCast(p,
OperatorKey.genOpKey(scope), fs.type);
cast.setFieldSchema(fs);
p.add(cast);
p.connect(proj, cast);
cast.setFieldSchema(fs.clone());
FuncSpec loadFuncSpec = null;
if(lo instanceof LOLoad) {
loadFuncSpec = ((LOLoad)lo).getInputFile().getFuncSpec();
} else if (lo instanceof LOStream) {
StreamingCommand command = ((LOStream)lo).getStreamingCommand();
HandleSpec streamOutputSpec = command.getOutputSpec();
loadFuncSpec = new FuncSpec(streamOutputSpec.getSpec());
} else {
int errCode = 2006;
String msg = "TypeCastInserter invoked with an invalid operator class name: " + lo.getClass().getSimpleName();
throw new OptimizerException(msg, errCode, PigException.BUG);
}
cast.setLoadFuncSpec(loadFuncSpec);
typeChanges.put(fs.canonicalName, fs.type);
if(determinedSchema == null) {
// Reset the loads field schema to byte array so that it
// will reflect reality.
fs.type = DataType.BYTEARRAY;
} else {
// Reset the type to what determinedSchema says it is
fs.type = determinedSchema.getField(i).type;
}
}
}
}