[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:
morrySnow
2023-11-03 14:01:25 +08:00
committed by GitHub
parent 9019a71770
commit 6892fc99f8
3 changed files with 38 additions and 22 deletions

View File

@ -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);
}

View File

@ -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) {