diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java index 0e049b4b90..7280463b0f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java @@ -21,7 +21,9 @@ import org.apache.doris.datasource.InternalCatalog; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.nereids.annotation.Developing; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.functions.AggCombinerFunctionBuilder; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; import org.apache.doris.nereids.trees.expressions.functions.FunctionBuilder; import org.apache.doris.nereids.trees.expressions.functions.udf.UdfBuilder; import org.apache.doris.nereids.types.DataType; @@ -156,18 +158,33 @@ public class FunctionRegistry { + "' which has " + arity + " arity. Candidate functions are: " + candidateHints); } if (candidateBuilders.size() > 1) { - String candidateHints = getCandidateHint(name, candidateBuilders); - // TODO: NereidsPlanner not supported override function by the same arity, we will support it later - if (ConnectContext.get() != null) { - try { - ConnectContext.get().getSessionVariable().enableFallbackToOriginalPlannerOnce(); - } catch (Throwable t) { - // ignore error + boolean needChooseOne = true; + List signatures = Lists.newArrayListWithCapacity(candidateBuilders.size()); + for (FunctionBuilder functionBuilder : candidateBuilders) { + if (functionBuilder instanceof UdfBuilder) { + signatures.addAll(((UdfBuilder) functionBuilder).getSignatures()); + } else { + needChooseOne = false; + break; } } + for (Object argument : arguments) { + if (!(argument instanceof Expression)) { + needChooseOne = false; + break; + } + } + if (needChooseOne) { + FunctionSignature signature = new UdfSignatureSearcher(signatures, (List) arguments).getSignature(); + for (int i = 0; i < signatures.size(); i++) { + if (signatures.get(i).equals(signature)) { + return candidateBuilders.get(i); + } + } + } + String candidateHints = getCandidateHint(name, candidateBuilders); throw new AnalysisException("Function '" + qualifiedName + "' is ambiguous: " + candidateHints); } - return candidateBuilders.get(0); } @@ -235,4 +252,63 @@ public class FunctionRegistry { .removeIf(builder -> ((UdfBuilder) builder).getArgTypes().equals(argTypes)); } } + + /** + * use for search appropriate signature for UDFs if candidate more than one. + */ + static class UdfSignatureSearcher implements ExplicitlyCastableSignature { + + private final List signatures; + private final List arguments; + + public UdfSignatureSearcher(List signatures, List arguments) { + this.signatures = signatures; + this.arguments = arguments; + } + + @Override + public List getSignatures() { + return signatures; + } + + @Override + public FunctionSignature getSignature() { + return searchSignature(signatures); + } + + @Override + public boolean nullable() { + throw new AnalysisException("could not call nullable on UdfSignatureSearcher"); + } + + @Override + public List children() { + return arguments; + } + + @Override + public Expression child(int index) { + return arguments.get(index); + } + + @Override + public int arity() { + return arguments.size(); + } + + @Override + public Optional getMutableState(String key) { + return Optional.empty(); + } + + @Override + public void setMutableState(String key, Object value) { + } + + @Override + public Expression withChildren(List children) { + throw new AnalysisException("could not call withChildren on UdfSignatureSearcher"); + + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSignature.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSignature.java index 4ff9448a33..4915073141 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSignature.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSignature.java @@ -30,7 +30,6 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.function.BiFunction; public class FunctionSignature { public final DataType returnType; @@ -78,21 +77,6 @@ public class FunctionSignature { return new FunctionSignature(returnType, hasVarArgs, argumentsTypes); } - /** - * change argument type by the signature's type and the corresponding argument's type - * @param arguments arguments - * @param transform param1: signature's type, param2: argument's type, return new type you want to change - * @return - */ - public FunctionSignature withArgumentTypes(List arguments, - BiFunction transform) { - List newTypes = Lists.newArrayList(); - for (int i = 0; i < arguments.size(); i++) { - newTypes.add(transform.apply(getArgType(i), arguments.get(i))); - } - return withArgumentTypes(hasVarArgs, newTypes); - } - /** * change argument type by the signature's type and the corresponding argument's type * @param arguments arguments @@ -145,6 +129,24 @@ public class FunctionSignature { .toString(); } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FunctionSignature signature = (FunctionSignature) o; + return hasVarArgs == signature.hasVarArgs && arity == signature.arity && Objects.equals(returnType, + signature.returnType) && Objects.equals(argumentsTypes, signature.argumentsTypes); + } + + @Override + public int hashCode() { + return Objects.hash(returnType, hasVarArgs, argumentsTypes, arity); + } + public static class FuncSigBuilder { public final DataType returnType; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java index 0aa0bfdf85..7b97335e77 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java @@ -32,7 +32,6 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.NullType; -import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; @@ -62,8 +61,7 @@ public class AliasUdf extends ScalarFunction implements ExplicitlyCastableSignat @Override public List getSignatures() { - return ImmutableList.of(Suppliers.memoize(() -> FunctionSignature - .of(NullType.INSTANCE, argTypes)).get()); + return ImmutableList.of(FunctionSignature.of(NullType.INSTANCE, argTypes)); } public List getParameters() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java index 2886b5cf4a..2bb832524e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions.functions.udf; +import org.apache.doris.catalog.FunctionSignature; import org.apache.doris.common.Pair; import org.apache.doris.common.util.ReflectionUtils; import org.apache.doris.nereids.analyzer.Scope; @@ -25,7 +26,6 @@ import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.functions.BoundFunction; -import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.util.TypeCoercionUtils; @@ -53,6 +53,11 @@ public class AliasUdfBuilder extends UdfBuilder { return aliasUdf.getArgTypes(); } + @Override + public List getSignatures() { + return aliasUdf.getSignatures(); + } + @Override public Class functionClass() { return AliasUdf.class; @@ -109,17 +114,4 @@ public class AliasUdfBuilder extends UdfBuilder { return Pair.of(udfAnalyzer.analyze(aliasUdf.getUnboundFunction()), boundAliasFunction); } - - private static class SlotReplacer extends DefaultExpressionRewriter> { - public static final SlotReplacer INSTANCE = new SlotReplacer(); - - public Expression replace(Expression expression, Map context) { - return expression.accept(this, context); - } - - @Override - public Expression visitSlotReference(SlotReference slot, Map context) { - return context.get(slot); - } - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java index 0d8ad443f5..802df2442f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions.functions.udf; +import org.apache.doris.catalog.FunctionSignature; import org.apache.doris.common.Pair; import org.apache.doris.common.util.ReflectionUtils; import org.apache.doris.nereids.trees.expressions.Expression; @@ -50,6 +51,11 @@ public class JavaUdafBuilder extends UdfBuilder { .collect(Collectors.toList())).get(); } + @Override + public List getSignatures() { + return udaf.getSignatures(); + } + @Override public Class functionClass() { return JavaUdaf.class; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java index 04d4741286..fb1184a9c1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions.functions.udf; +import org.apache.doris.catalog.FunctionSignature; import org.apache.doris.common.Pair; import org.apache.doris.common.util.ReflectionUtils; import org.apache.doris.nereids.trees.expressions.Expression; @@ -52,6 +53,11 @@ public class JavaUdfBuilder extends UdfBuilder { .collect(Collectors.toList())).get(); } + @Override + public List getSignatures() { + return udf.getSignatures(); + } + @Override public Class functionClass() { return JavaUdf.class; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/UdfBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/UdfBuilder.java index 892d9a4312..2c57cfad1b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/UdfBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/UdfBuilder.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions.functions.udf; +import org.apache.doris.catalog.FunctionSignature; import org.apache.doris.nereids.trees.expressions.functions.FunctionBuilder; import org.apache.doris.nereids.types.DataType; @@ -27,4 +28,6 @@ import java.util.List; */ public abstract class UdfBuilder extends FunctionBuilder { public abstract List getArgTypes(); + + public abstract List getSignatures(); }