[opt](nereids) optimize not found function error message (#47919) (#48102)

cherry pick from #47919
This commit is contained in:
924060929
2025-02-21 10:13:46 +08:00
committed by GitHub
parent 3738d0fddc
commit a3753c7edb
8 changed files with 116 additions and 1 deletions

View File

@ -23,6 +23,8 @@ 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.BoundFunction;
import org.apache.doris.nereids.trees.expressions.functions.BuiltinFunctionBuilder;
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;
@ -37,6 +39,8 @@ import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -227,7 +231,25 @@ public class FunctionRegistry {
public String getCandidateHint(String name, List<FunctionBuilder> candidateBuilders) {
return candidateBuilders.stream()
.map(builder -> name + builder.toString())
.filter(builder -> {
if (builder instanceof BuiltinFunctionBuilder) {
Constructor<BoundFunction> builderMethod
= ((BuiltinFunctionBuilder) builder).getBuilderMethod();
if (Modifier.isAbstract(builderMethod.getModifiers())
|| !Modifier.isPublic(builderMethod.getModifiers())) {
return false;
}
for (Class<?> parameterType : builderMethod.getParameterTypes()) {
if (!Expression.class.isAssignableFrom(parameterType)
&& !(parameterType.isArray()
&& Expression.class.isAssignableFrom(parameterType.getComponentType()))) {
return false;
}
}
}
return true;
})
.map(builder -> name + builder.parameterDisplayString())
.collect(Collectors.joining(", ", "[", "]"));
}

View File

@ -145,6 +145,11 @@ public class AggCombinerFunctionBuilder extends FunctionBuilder {
return null;
}
@Override
public String parameterDisplayString() {
return nestedBuilder.parameterDisplayString();
}
public static boolean isAggStateCombinator(String name) {
return name.toLowerCase().endsWith(STATE_SUFFIX) || name.toLowerCase().endsWith(MERGE_SUFFIX)
|| name.toLowerCase().endsWith(UNION_SUFFIX) || name.toLowerCase().endsWith(FOREACH_SUFFIX);

View File

@ -53,6 +53,10 @@ public class BuiltinFunctionBuilder extends FunctionBuilder {
this.isVariableLength = arity > 0 && builderMethod.getParameterTypes()[arity - 1].isArray();
}
public Constructor<BoundFunction> getBuilderMethod() {
return builderMethod;
}
@Override
public Class<? extends BoundFunction> functionClass() {
return functionClass;
@ -146,4 +150,16 @@ public class BuiltinFunctionBuilder extends FunctionBuilder {
.collect(ImmutableList.toImmutableList());
}
@Override
public String parameterDisplayString() {
return Arrays.stream(builderMethod.getParameterTypes())
.map(p -> {
if (p.isArray()) {
return p.getComponentType().getSimpleName() + "...";
} else {
return p.getSimpleName();
}
})
.collect(Collectors.joining(", ", "(", ")"));
}
}

View File

@ -47,4 +47,9 @@ public abstract class FunctionBuilder {
*/
public abstract Pair<? extends Expression, ? extends BoundFunction> build(
String name, List<? extends Object> arguments);
/**
* return the parameters string for display candidate functions, for example: `(int, decimal, varchar)`
*/
public abstract String parameterDisplayString();
}

View File

@ -114,4 +114,11 @@ public class AliasUdfBuilder extends UdfBuilder {
return Pair.of(udfAnalyzer.analyze(aliasUdf.getUnboundFunction()), boundAliasFunction);
}
@Override
public String parameterDisplayString() {
return aliasUdf.getArgTypes().stream()
.map(DataType::toString)
.collect(Collectors.joining(", ", "(", ")"));
}
}

View File

@ -85,4 +85,19 @@ public class JavaUdafBuilder extends UdfBuilder {
.collect(Collectors.toList()))
);
}
@Override
public String parameterDisplayString() {
StringBuilder string = new StringBuilder("(");
for (int i = 0; i < udaf.getArgumentsTypes().size(); ++i) {
if (i > 0) {
string.append(", ");
}
string.append(udaf.getArgumentsTypes().get(i));
if (isVarArgs && i + 1 == udaf.getArgumentsTypes().size()) {
string.append("...");
}
}
return string.append(")").toString();
}
}

View File

@ -90,4 +90,19 @@ public class JavaUdfBuilder extends UdfBuilder {
}
return Pair.ofSame(udf.withChildren(processedExprs));
}
@Override
public String parameterDisplayString() {
StringBuilder string = new StringBuilder("(");
for (int i = 0; i < udf.getArgumentsTypes().size(); ++i) {
if (i > 0) {
string.append(", ");
}
string.append(udf.getArgumentsTypes().get(i));
if (isVarArgs && i + 1 == udf.getArgumentsTypes().size()) {
string.append("...");
}
}
return string.append(")").toString();
}
}

View File

@ -0,0 +1,30 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
suite("not_found_function") {
sql "set enable_fallback_to_original_planner=false"
test {
sql "select group_concat()"
exception "Can not found function 'group_concat' which has 0 arity. Candidate functions are: [group_concat(Expression, Expression...)]"
}
test {
sql "select sum()"
exception "Can not found function 'sum' which has 0 arity. Candidate functions are: [sum(Expression)]"
}
}