use of org.apache.drill.exec.expr.fn.DrillFuncHolder in project drill by apache.
the class DefaultFunctionResolver method getBestMatch.
@Override
public DrillFuncHolder getBestMatch(List<DrillFuncHolder> methods, FunctionCall call) {
int bestcost = Integer.MAX_VALUE;
int currcost = Integer.MAX_VALUE;
DrillFuncHolder bestmatch = null;
final List<DrillFuncHolder> bestMatchAlternatives = new LinkedList<>();
for (DrillFuncHolder h : methods) {
final List<TypeProtos.MajorType> argumentTypes = Lists.newArrayList();
for (LogicalExpression expression : call.args) {
argumentTypes.add(expression.getMajorType());
}
currcost = TypeCastRules.getCost(argumentTypes, h);
// if cost is lower than 0, func implementation is not matched, either w/ or w/o implicit casts
if (currcost < 0) {
continue;
}
if (currcost < bestcost) {
bestcost = currcost;
bestmatch = h;
bestMatchAlternatives.clear();
} else if (currcost == bestcost) {
// keep log of different function implementations that have the same best cost
bestMatchAlternatives.add(h);
}
}
if (bestcost < 0) {
//TODO: raise exception here?
return null;
} else {
if (AssertionUtil.isAssertionsEnabled() && bestMatchAlternatives.size() > 0) {
/*
* There are other alternatives to the best match function which could have been selected
* Log the possible functions and the chose implementation and raise an exception
*/
logger.error("Chosen function impl: " + bestmatch.toString());
// printing the possible matches
logger.error("Printing all the possible functions that could have matched: ");
for (DrillFuncHolder holder : bestMatchAlternatives) {
logger.error(holder.toString());
}
throw new AssertionError("Multiple functions with best cost found");
}
return bestmatch;
}
}
use of org.apache.drill.exec.expr.fn.DrillFuncHolder in project drill by apache.
the class ExactFunctionResolver method getBestMatch.
/*
* This function resolves the input call to a func holder only if all
* the input argument types match exactly with the func holder arguments. This is used when we
* are trying to inject an implicit cast and do not want to inject another implicit
* cast
*/
@Override
public DrillFuncHolder getBestMatch(List<DrillFuncHolder> methods, FunctionCall call) {
int currcost;
for (DrillFuncHolder h : methods) {
final List<TypeProtos.MajorType> argumentTypes = Lists.newArrayList();
for (LogicalExpression expression : call.args) {
argumentTypes.add(expression.getMajorType());
}
currcost = TypeCastRules.getCost(argumentTypes, h);
// Return if we found a function that has an exact match with the input arguments
if (currcost == 0) {
return h;
}
}
// No match found
return null;
}
use of org.apache.drill.exec.expr.fn.DrillFuncHolder in project drill by apache.
the class TypeInferenceUtils method resolveDrillFuncHolder.
private static DrillFuncHolder resolveDrillFuncHolder(final SqlOperatorBinding opBinding, final List<DrillFuncHolder> functions) {
final FunctionCall functionCall = convertSqlOperatorBindingToFunctionCall(opBinding);
final FunctionResolver functionResolver = FunctionResolverFactory.getResolver(functionCall);
final DrillFuncHolder func = functionResolver.getBestMatch(functions, functionCall);
// if no DrillFuncHolder matched for the given list of operand types
if (func == null) {
String operandTypes = "";
for (int i = 0; i < opBinding.getOperandCount(); ++i) {
operandTypes += opBinding.getOperandType(i).getSqlTypeName();
if (i < opBinding.getOperandCount() - 1) {
operandTypes += ",";
}
}
throw UserException.functionError().message(String.format("%s does not support operand types (%s)", opBinding.getOperator().getName(), operandTypes)).build(logger);
}
return func;
}
use of org.apache.drill.exec.expr.fn.DrillFuncHolder in project drill by apache.
the class LocalFunctionRegistry method registerOperatorsWithoutInference.
private void registerOperatorsWithoutInference(DrillOperatorTable operatorTable, Map<String, Collection<DrillFuncHolder>> registeredFunctions) {
SqlOperator op;
for (Entry<String, Collection<DrillFuncHolder>> function : registeredFunctions.entrySet()) {
Set<Integer> argCounts = Sets.newHashSet();
String name = function.getKey().toUpperCase();
for (DrillFuncHolder func : function.getValue()) {
if (argCounts.add(func.getParamCount())) {
if (func.isAggregating()) {
op = new DrillSqlAggOperatorWithoutInference(name, func.getParamCount());
} else {
boolean isDeterministic;
// into literals
if (DrillConstExecutor.NON_REDUCIBLE_TYPES.contains(func.getReturnType().getMinorType())) {
isDeterministic = false;
} else {
isDeterministic = func.isDeterministic();
}
op = new DrillSqlOperatorWithoutInference(name, func.getParamCount(), func.getReturnType(), isDeterministic, func.isNiladic());
}
operatorTable.addOperatorWithoutInference(function.getKey(), op);
}
}
}
}
use of org.apache.drill.exec.expr.fn.DrillFuncHolder in project drill by apache.
the class LocalFunctionRegistry method registerOperatorsWithInference.
private void registerOperatorsWithInference(DrillOperatorTable operatorTable, Map<String, Collection<DrillFuncHolder>> registeredFunctions) {
final Map<String, DrillSqlOperator.DrillSqlOperatorBuilder> map = Maps.newHashMap();
final Map<String, DrillSqlAggOperator.DrillSqlAggOperatorBuilder> mapAgg = Maps.newHashMap();
for (Entry<String, Collection<DrillFuncHolder>> function : registeredFunctions.entrySet()) {
final ArrayListMultimap<Pair<Integer, Integer>, DrillFuncHolder> functions = ArrayListMultimap.create();
final ArrayListMultimap<Integer, DrillFuncHolder> aggregateFunctions = ArrayListMultimap.create();
final String name = function.getKey().toUpperCase();
boolean isDeterministic = true;
boolean isNiladic = false;
for (DrillFuncHolder func : function.getValue()) {
final int paramCount = func.getParamCount();
if (func.isAggregating()) {
aggregateFunctions.put(paramCount, func);
} else {
final Pair<Integer, Integer> argNumberRange;
if (registeredFuncNameToArgRange.containsKey(name)) {
argNumberRange = registeredFuncNameToArgRange.get(name);
} else {
argNumberRange = Pair.of(func.getParamCount(), func.getParamCount());
}
functions.put(argNumberRange, func);
}
if (!func.isDeterministic()) {
isDeterministic = false;
}
if (func.isNiladic()) {
isNiladic = true;
}
}
for (Entry<Pair<Integer, Integer>, Collection<DrillFuncHolder>> entry : functions.asMap().entrySet()) {
final Pair<Integer, Integer> range = entry.getKey();
final int max = range.getRight();
final int min = range.getLeft();
if (!map.containsKey(name)) {
map.put(name, new DrillSqlOperator.DrillSqlOperatorBuilder().setName(name));
}
final DrillSqlOperator.DrillSqlOperatorBuilder drillSqlOperatorBuilder = map.get(name);
drillSqlOperatorBuilder.addFunctions(entry.getValue()).setArgumentCount(min, max).setDeterministic(isDeterministic).setNiladic(isNiladic);
}
for (Entry<Integer, Collection<DrillFuncHolder>> entry : aggregateFunctions.asMap().entrySet()) {
if (!mapAgg.containsKey(name)) {
mapAgg.put(name, new DrillSqlAggOperator.DrillSqlAggOperatorBuilder().setName(name));
}
final DrillSqlAggOperator.DrillSqlAggOperatorBuilder drillSqlAggOperatorBuilder = mapAgg.get(name);
drillSqlAggOperatorBuilder.addFunctions(entry.getValue()).setArgumentCount(entry.getKey(), entry.getKey());
}
}
for (final Entry<String, DrillSqlOperator.DrillSqlOperatorBuilder> entry : map.entrySet()) {
operatorTable.addOperatorWithInference(entry.getKey(), entry.getValue().build());
}
for (final Entry<String, DrillSqlAggOperator.DrillSqlAggOperatorBuilder> entry : mapAgg.entrySet()) {
operatorTable.addOperatorWithInference(entry.getKey(), entry.getValue().build());
}
}
Aggregations