private FuncSpec bestFitMatchWithByteArrays(List<FuncSpec> funcSpecs,
Schema s, LOUserFunc func) throws VisitorException {
List<Pair<Long, FuncSpec>> scoreFuncSpecList = new ArrayList<Pair<Long,FuncSpec>>();
for (Iterator<FuncSpec> iterator = funcSpecs.iterator(); iterator
.hasNext();) {
FuncSpec fs = iterator.next();
long score = fitPossible(s, fs.getInputArgsSchema());
if (score != INF) {
scoreFuncSpecList.add(new Pair<Long, FuncSpec>(score, fs));
}
}
// if no candidates found, return null
if(scoreFuncSpecList.size() == 0)
return null;
if(scoreFuncSpecList.size() > 1) {
// sort the candidates based on score
Collections.sort(scoreFuncSpecList, new ScoreFuncSpecListComparator());
// if there are two (or more) candidates with the same *lowest* score
// we cannot choose one of them - notify the user
if (scoreFuncSpecList.get(0).first == scoreFuncSpecList.get(1).first) {
int errCode = 1046;
String msg = "Multiple matching functions for "
+ func.getFuncSpec() + " with input schemas: " + "("
+ scoreFuncSpecList.get(0).second.getInputArgsSchema() + ", "
+ scoreFuncSpecList.get(1).second.getInputArgsSchema() + "). Please use an explicit cast.";
msgCollector.collect(msg, MessageType.Error);
throw new TypeCheckerException(msg, errCode, PigException.INPUT);
}
// now consider the bytearray fields
List<Integer> byteArrayPositions = getByteArrayPositions(s);
// make sure there is only one type to "cast to" for the byte array
// positions among the candidate funcSpecs
Map<Integer, Pair<FuncSpec, Byte>> castToMap = new HashMap<Integer, Pair<FuncSpec, Byte>>();
for (Iterator<Pair<Long, FuncSpec>> it = scoreFuncSpecList.iterator(); it.hasNext();) {
FuncSpec funcSpec = it.next().second;
Schema sch = funcSpec.getInputArgsSchema();
for (Iterator<Integer> iter = byteArrayPositions.iterator(); iter
.hasNext();) {
Integer i = iter.next();
try {
if (!castToMap.containsKey(i)) {
// first candidate
castToMap.put(i, new Pair<FuncSpec, Byte>(funcSpec, sch
.getField(i).type));
} else {
// make sure the existing type from an earlier candidate
// matches
Pair<FuncSpec, Byte> existingPair = castToMap.get(i);
if (sch.getField(i).type != existingPair.second) {
int errCode = 1046;
String msg = "Multiple matching functions for "
+ func.getFuncSpec() + " with input schema: "
+ "(" + existingPair.first.getInputArgsSchema()
+ ", " + funcSpec.getInputArgsSchema()
+ "). Please use an explicit cast.";
msgCollector.collect(msg, MessageType.Error);
throw new TypeCheckerException(msg, errCode, PigException.INPUT);
}
}