[fix](Nereids) only search internal funcftion when dbName is empty (#26296)
if call function with database name. we should only search UDF
This commit is contained in:
@ -33,6 +33,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -86,24 +87,31 @@ public class FunctionRegistry {
|
||||
|
||||
// currently we only find function by name and arity and args' types.
|
||||
public FunctionBuilder findFunctionBuilder(String dbName, String name, List<?> arguments) {
|
||||
List<FunctionBuilder> functionBuilders = null;
|
||||
int arity = arguments.size();
|
||||
List<FunctionBuilder> functionBuilders = name2InternalBuiltinBuilders.get(name.toLowerCase());
|
||||
if (CollectionUtils.isEmpty(functionBuilders) && AggStateFunctionBuilder.isAggStateCombinator(name)) {
|
||||
String nestedName = AggStateFunctionBuilder.getNestedName(name);
|
||||
String combinatorSuffix = AggStateFunctionBuilder.getCombinatorSuffix(name);
|
||||
String qualifiedName = StringUtils.isEmpty(dbName) ? name : dbName + "." + name;
|
||||
|
||||
functionBuilders = name2InternalBuiltinBuilders.get(nestedName.toLowerCase());
|
||||
|
||||
if (functionBuilders != null) {
|
||||
functionBuilders = functionBuilders.stream().map(builder -> {
|
||||
return new AggStateFunctionBuilder(combinatorSuffix, builder);
|
||||
}).filter(functionBuilder -> functionBuilder.canApply(arguments)).collect(Collectors.toList());
|
||||
if (StringUtils.isEmpty(dbName)) {
|
||||
// search internal function only if dbName is empty
|
||||
functionBuilders = name2InternalBuiltinBuilders.get(name.toLowerCase());
|
||||
if (CollectionUtils.isEmpty(functionBuilders) && AggStateFunctionBuilder.isAggStateCombinator(name)) {
|
||||
String nestedName = AggStateFunctionBuilder.getNestedName(name);
|
||||
String combinatorSuffix = AggStateFunctionBuilder.getCombinatorSuffix(name);
|
||||
functionBuilders = name2InternalBuiltinBuilders.get(nestedName.toLowerCase());
|
||||
if (functionBuilders != null) {
|
||||
functionBuilders = functionBuilders.stream()
|
||||
.map(builder -> new AggStateFunctionBuilder(combinatorSuffix, builder))
|
||||
.filter(functionBuilder -> functionBuilder.canApply(arguments))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (functionBuilders == null || functionBuilders.isEmpty()) {
|
||||
|
||||
// search udf
|
||||
if (CollectionUtils.isEmpty(functionBuilders)) {
|
||||
functionBuilders = findUdfBuilder(dbName, name);
|
||||
if (functionBuilders == null || functionBuilders.isEmpty()) {
|
||||
throw new AnalysisException("Can not found function '" + name + "'");
|
||||
throw new AnalysisException("Can not found function '" + qualifiedName + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,15 +121,15 @@ public class FunctionRegistry {
|
||||
.collect(Collectors.toList());
|
||||
if (candidateBuilders.isEmpty()) {
|
||||
String candidateHints = getCandidateHint(name, functionBuilders);
|
||||
throw new AnalysisException("Can not found function '" + name
|
||||
throw new AnalysisException("Can not found function '" + qualifiedName
|
||||
+ "' which has " + arity + " arity. Candidate functions are: " + candidateHints);
|
||||
}
|
||||
|
||||
if (candidateBuilders.size() > 1) {
|
||||
String candidateHints = getCandidateHint(name, candidateBuilders);
|
||||
// NereidsPlanner not supported override function by the same arity, should we support it?
|
||||
throw new AnalysisException("Function '" + name + "' is ambiguous: " + candidateHints);
|
||||
throw new AnalysisException("Function '" + qualifiedName + "' is ambiguous: " + candidateHints);
|
||||
}
|
||||
|
||||
return candidateBuilders.get(0);
|
||||
}
|
||||
|
||||
|
||||
@ -59,6 +59,7 @@ import org.apache.doris.nereids.types.DataType;
|
||||
import org.apache.doris.nereids.util.TypeCoercionUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -142,7 +143,6 @@ public class FunctionBinder extends AbstractExpressionRewriteRule {
|
||||
|
||||
// bind function
|
||||
FunctionRegistry functionRegistry = Env.getCurrentEnv().getFunctionRegistry();
|
||||
String functionName = unboundFunction.getName();
|
||||
List<Object> arguments = unboundFunction.isDistinct()
|
||||
? ImmutableList.builder()
|
||||
.add(unboundFunction.isDistinct())
|
||||
@ -150,14 +150,17 @@ public class FunctionBinder extends AbstractExpressionRewriteRule {
|
||||
.build()
|
||||
: (List) unboundFunction.getArguments();
|
||||
|
||||
// we will change arithmetic function like add(), subtract(), bitnot() to the corresponding objects rather than
|
||||
// BoundFunction.
|
||||
ArithmeticFunctionBinder functionBinder = new ArithmeticFunctionBinder();
|
||||
if (functionBinder.isBinaryArithmetic(unboundFunction.getName())) {
|
||||
return functionBinder.bindBinaryArithmetic(unboundFunction.getName(), unboundFunction.children())
|
||||
.accept(this, context);
|
||||
if (StringUtils.isEmpty(unboundFunction.getDbName())) {
|
||||
// we will change arithmetic function like add(), subtract(), bitnot()
|
||||
// to the corresponding objects rather than BoundFunction.
|
||||
ArithmeticFunctionBinder functionBinder = new ArithmeticFunctionBinder();
|
||||
if (functionBinder.isBinaryArithmetic(unboundFunction.getName())) {
|
||||
return functionBinder.bindBinaryArithmetic(unboundFunction.getName(), unboundFunction.children())
|
||||
.accept(this, context);
|
||||
}
|
||||
}
|
||||
|
||||
String functionName = unboundFunction.getName();
|
||||
FunctionBuilder builder = functionRegistry.findFunctionBuilder(
|
||||
unboundFunction.getDbName(), functionName, arguments);
|
||||
if (builder instanceof AliasUdfBuilder) {
|
||||
|
||||
Reference in New Issue
Block a user