morrySnow commented on code in PR #18257: URL: https://github.com/apache/doris/pull/18257#discussion_r1246071056
########## fe/fe-core/src/main/java/org/apache/doris/catalog/Database.java: ########## @@ -715,28 +715,32 @@ public void setName(String name) { public synchronized void addFunction(Function function, boolean ifNotExists) throws UserException { function.checkWritable(); - if (FunctionUtil.addFunctionImpl(function, ifNotExists, false, name2Function)) { + if (FunctionUtil.addFunctionImpl(function, ifNotExists, false, name2Function) + && FunctionUtil.translateToNereids(this.getFullName(), function)) { Review Comment: translateToNereids failed should not block log function, because nereids could not handle all type now ########## fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java: ########## @@ -251,6 +251,9 @@ public String toSqlImpl() { } else { return label; } + } else if (desc == null) { + // virtual slot of an alias function + return col; Review Comment: add more details to explain why need add this if branch ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java: ########## @@ -110,4 +126,50 @@ public String getCandidateHint(String name, List<FunctionBuilder> candidateBuild .map(builder -> name + builder.toString()) .collect(Collectors.joining(", ", "[", "]")); } + + + public void addUdf(String dbName, String name, UdfBuilder builder) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders + .computeIfAbsent(dbName, k -> Maps.newHashMap()); + builders.computeIfAbsent(name, k -> Lists.newArrayList()).add(builder); + } + } + + public void dropUdf(String dbName, String name, List<DataType> argTypes) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders.getOrDefault(dbName, ImmutableMap.of()); + builders.getOrDefault(name, Lists.newArrayList()).removeIf(builder -> ((UdfBuilder) builder).getArgTypes() + .equals(argTypes)); + } + } + + /** + * for test + */ + public List<FunctionBuilder> findUdfBuilder(String dbName, String name) { Review Comment: put all findxxxBuilder functions togather ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java: ########## @@ -110,4 +126,50 @@ public String getCandidateHint(String name, List<FunctionBuilder> candidateBuild .map(builder -> name + builder.toString()) .collect(Collectors.joining(", ", "[", "]")); } + + + public void addUdf(String dbName, String name, UdfBuilder builder) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders + .computeIfAbsent(dbName, k -> Maps.newHashMap()); + builders.computeIfAbsent(name, k -> Lists.newArrayList()).add(builder); + } + } + + public void dropUdf(String dbName, String name, List<DataType> argTypes) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders.getOrDefault(dbName, ImmutableMap.of()); + builders.getOrDefault(name, Lists.newArrayList()).removeIf(builder -> ((UdfBuilder) builder).getArgTypes() + .equals(argTypes)); + } + } + + /** + * for test + */ Review Comment: this function is not only for test, if u mean public for test, u could just remove public, and should work fine ########## fe/fe-core/src/main/java/org/apache/doris/catalog/GlobalFunctionMgr.java: ########## @@ -35,6 +37,8 @@ */ public class GlobalFunctionMgr extends MetaObject { + public static final Logger LOG = LogManager.getLogger(GlobalFunctionMgr.class); Review Comment: why add this? ########## fe/fe-core/src/main/java/org/apache/doris/catalog/GlobalFunctionMgr.java: ########## @@ -60,7 +64,8 @@ public void readFields(DataInput in) throws IOException { public synchronized void addFunction(Function function, boolean ifNotExists) throws UserException { function.setGlobal(true); function.checkWritable(); - if (FunctionUtil.addFunctionImpl(function, ifNotExists, false, name2Function)) { + if (FunctionUtil.addFunctionImpl(function, ifNotExists, false, name2Function) + && FunctionUtil.translateToNereids(null, function)) { Review Comment: same as code block in Database, should not block log ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java: ########## @@ -41,9 +48,12 @@ @ThreadSafe public class FunctionRegistry { private final Map<String, List<FunctionBuilder>> name2Builders; + private final Map<String, Map<String, List<FunctionBuilder>>> name2UdfBuilders; + private static final String GLOBAL_FUNCTION = "__GLOBAL_FUNCTION__"; Review Comment: what's this? BTW, `static final` should upper than `final` and sep with a blank line ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/Udf.java: ########## @@ -0,0 +1,49 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions; + +import org.apache.doris.catalog.Function; +import org.apache.doris.catalog.Function.NullableMode; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.trees.expressions.Expression; + +import java.util.List; + +/** + * interface for udf + */ +public interface Udf extends ComputeNullable { + @Override + default boolean nullable() { + NullableMode mode = getNullableMode(); + if (mode == NullableMode.ALWAYS_NOT_NULLABLE) { + return false; + } else if (mode == NullableMode.ALWAYS_NULLABLE || mode == NullableMode.CUSTOM) { + return true; + } else if (mode == NullableMode.DEPEND_ON_ARGUMENT) { + return children().stream().allMatch(ExpressionTrait::nullable); Review Comment: why all match? i think should be any match ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java: ########## @@ -0,0 +1,145 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.udf; + +import org.apache.doris.catalog.AliasFunction; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.analyzer.UnboundFunction; +import org.apache.doris.nereids.analyzer.UnboundSlot; +import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.VirtualSlotReference; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.scalar.ScalarFunction; +import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; +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; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * alias function + */ +public class AliasUdf extends ScalarFunction implements ExplicitlyCastableSignature { + private final UnboundFunction unboundFunction; + private final List<String> parameters; + private final List<DataType> argTypes; + private DataType retType; Review Comment: useless attr ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionUtil.java: ########## @@ -217,4 +223,31 @@ public static String reAcquireDbName(Analyzer analyzer, String dbName, String cl } return dbName; } + + public static boolean translateToNereids(String dbName, Function function) { + try { + if (function instanceof AliasFunction) { + AliasUdf.translateToNereidsFunction(dbName, ((AliasFunction) function)); + } else if (function instanceof ScalarFunction) { + JavaUdf.translateToNereidsFunction(dbName, ((ScalarFunction) function)); + } else if (function instanceof AggregateFunction) { + JavaUdaf.translateToNereidsFunction(dbName, ((AggregateFunction) function)); + } + } catch (Exception e) { + LOG.warn("Nereids create function {}:{} failed", dbName, function.getFunctionName().getFunction()); + } + return true; + } + + public static boolean dropFromNereids(String dbName, FunctionSearchDesc function) { + try { + String fnName = function.getName().getFunction(); + List<DataType> argTypes = Arrays.stream(function.getArgTypes()).map(DataType::fromCatalogType) + .collect(Collectors.toList()); + Env.getCurrentEnv().getFunctionRegistry().dropUdf(dbName, fnName, argTypes); + } catch (Exception e) { + LOG.warn("Nereids drop function {}:{} failed", dbName, function.getName()); Review Comment: should return false here. and log exception stack in LOG.warn ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java: ########## @@ -110,4 +126,50 @@ public String getCandidateHint(String name, List<FunctionBuilder> candidateBuild .map(builder -> name + builder.toString()) .collect(Collectors.joining(", ", "[", "]")); } + + + public void addUdf(String dbName, String name, UdfBuilder builder) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders + .computeIfAbsent(dbName, k -> Maps.newHashMap()); + builders.computeIfAbsent(name, k -> Lists.newArrayList()).add(builder); + } + } + + public void dropUdf(String dbName, String name, List<DataType> argTypes) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders.getOrDefault(dbName, ImmutableMap.of()); + builders.getOrDefault(name, Lists.newArrayList()).removeIf(builder -> ((UdfBuilder) builder).getArgTypes() + .equals(argTypes)); + } + } + + /** + * for test + */ + public List<FunctionBuilder> findUdfBuilder(String dbName, String name) { + List<String> scopes = ImmutableList.of(GLOBAL_FUNCTION); + if (ConnectContext.get() != null) { + dbName = ClusterNamespace.getFullName(ConnectContext.get().getClusterName(), + dbName == null ? ConnectContext.get().getDatabase() : dbName); Review Comment: if we need do getFullName here, we should do getFullName in `addUdf` and `dropUdf`, or we should do `getFullName` out of getFunctionBuilder. this mean we receive full database name or simple database name for all functions in this class uniformly ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java: ########## @@ -110,4 +126,50 @@ public String getCandidateHint(String name, List<FunctionBuilder> candidateBuild .map(builder -> name + builder.toString()) .collect(Collectors.joining(", ", "[", "]")); } + + + public void addUdf(String dbName, String name, UdfBuilder builder) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders + .computeIfAbsent(dbName, k -> Maps.newHashMap()); + builders.computeIfAbsent(name, k -> Lists.newArrayList()).add(builder); + } + } + + public void dropUdf(String dbName, String name, List<DataType> argTypes) { + if (dbName == null) { + dbName = GLOBAL_FUNCTION; + } + synchronized (name2UdfBuilders) { + Map<String, List<FunctionBuilder>> builders = name2UdfBuilders.getOrDefault(dbName, ImmutableMap.of()); + builders.getOrDefault(name, Lists.newArrayList()).removeIf(builder -> ((UdfBuilder) builder).getArgTypes() + .equals(argTypes)); + } + } + + /** + * for test + */ + public List<FunctionBuilder> findUdfBuilder(String dbName, String name) { + List<String> scopes = ImmutableList.of(GLOBAL_FUNCTION); + if (ConnectContext.get() != null) { + dbName = ClusterNamespace.getFullName(ConnectContext.get().getClusterName(), + dbName == null ? ConnectContext.get().getDatabase() : dbName); + scopes = ImmutableList.of(dbName, GLOBAL_FUNCTION); + } + + synchronized (name2UdfBuilders) { + for (String scope : scopes) { + List<FunctionBuilder> candidate = name2UdfBuilders.getOrDefault(scope, ImmutableMap.of()) + .get(name.toLowerCase()); + if (candidate != null && !candidate.isEmpty()) { + return candidate; + } + } + } + throw new AnalysisException(String.format("Can not find udf named %s in database %s", name, dbName)); Review Comment: should not throw exception here, just return empty candidate ########## fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java: ########## @@ -41,9 +48,12 @@ @ThreadSafe public class FunctionRegistry { private final Map<String, List<FunctionBuilder>> name2Builders; Review Comment: change this map named to like `name2InternalFunctionBuilder` to indicate this builder only handle internal functions ########## fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FunctionBinder.java: ########## @@ -103,9 +105,14 @@ public Expression visitUnboundFunction(UnboundFunction unboundFunction, Expressi .accept(this, context); } - FunctionBuilder builder = functionRegistry.findFunctionBuilder(functionName, arguments); + FunctionBuilder builder = functionRegistry.findFunctionBuilder(unboundFunction.getDbName(), + functionName, arguments); BoundFunction boundFunction = builder.build(functionName, arguments); - return TypeCoercionUtils.processBoundFunction(boundFunction); + if (builder instanceof AliasUdfBuilder) { + return boundFunction; Review Comment: add comment to explain why not need do processBoundFunction ########## fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FunctionBinder.java: ########## @@ -86,7 +88,7 @@ public Expression visitUnboundFunction(UnboundFunction unboundFunction, Expressi .map(e -> e.accept(this, context)).collect(Collectors.toList())); // bind function - FunctionRegistry functionRegistry = context.cascadesContext.getConnectContext().getFunctionRegistry(); + FunctionRegistry functionRegistry = Env.getCurrentEnv().getFunctionRegistry(); Review Comment: why get function registry from env? ########## fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java: ########## Review Comment: i think u chould change the logical in branch `unboundStars.size() > 0` because we could create a function with same name as internal functions ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/Udf.java: ########## @@ -0,0 +1,49 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions; + +import org.apache.doris.catalog.Function; +import org.apache.doris.catalog.Function.NullableMode; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.trees.expressions.Expression; + +import java.util.List; + +/** + * interface for udf + */ +public interface Udf extends ComputeNullable { + @Override + default boolean nullable() { + NullableMode mode = getNullableMode(); + if (mode == NullableMode.ALWAYS_NOT_NULLABLE) { + return false; + } else if (mode == NullableMode.ALWAYS_NULLABLE || mode == NullableMode.CUSTOM) { Review Comment: what's mean about CUSTOM? why just return true? ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java: ########## @@ -0,0 +1,145 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.udf; + +import org.apache.doris.catalog.AliasFunction; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.analyzer.UnboundFunction; +import org.apache.doris.nereids.analyzer.UnboundSlot; +import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.VirtualSlotReference; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.scalar.ScalarFunction; +import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; +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; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * alias function + */ +public class AliasUdf extends ScalarFunction implements ExplicitlyCastableSignature { + private final UnboundFunction unboundFunction; + private final List<String> parameters; + private final List<DataType> argTypes; + private DataType retType; + + /** + * constructor + */ + public AliasUdf(String name, List<DataType> argTypes, UnboundFunction unboundFunction, + List<String> parameters, Expression... arguments) { + super(name, arguments); + this.argTypes = argTypes; + this.unboundFunction = unboundFunction; + this.parameters = parameters; + } + + @Override + public List<FunctionSignature> getSignatures() { + return ImmutableList.of(Suppliers.memoize(() -> FunctionSignature + .of(NullType.INSTANCE, argTypes)).get()); + } + + public List<String> getParameters() { + return parameters; + } + + public UnboundFunction getUnboundFunction() { + return unboundFunction; + } + + public List<DataType> getArgTypes() { + return argTypes; + } + + @Override + public boolean nullable() { + return false; + } + + /** + * translate catalog alias function to nereids alias function + */ + public static void translateToNereidsFunction(String dbName, AliasFunction function) { + String functionSql = function.getOriginFunction().toSql(); + Expression parsedFunction = new NereidsParser().parseExpression(functionSql); + + Map<String, VirtualSlotReference> replaceMap = Maps.newHashMap(); + for (int i = 0; i < function.getNumArgs(); ++i) { + replaceMap.put(function.getParameters().get(i), + new VirtualSlotReference( Review Comment: should not use this class, it is only used for Grouping function ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java: ########## @@ -0,0 +1,110 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.udf; + +import org.apache.doris.common.util.ReflectionUtils; +import org.apache.doris.nereids.rules.expression.rules.FunctionBinder; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.VirtualSlotReference; +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; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * alias function builder + */ +public class AliasUdfBuilder extends UdfBuilder { + private final AliasUdf aliasUdf; + + public AliasUdfBuilder(AliasUdf aliasUdf) { + this.aliasUdf = aliasUdf; + } + + @Override + public List<DataType> getArgTypes() { + return aliasUdf.getArgTypes(); + } + + @Override + public boolean canApply(List<?> arguments) { + if (arguments.size() != aliasUdf.arity()) { + return false; + } + for (Object argument : arguments) { + if (!(argument instanceof Expression)) { + Optional<Class> primitiveType = ReflectionUtils.getPrimitiveType(argument.getClass()); + if (!primitiveType.isPresent() || !Expression.class.isAssignableFrom(primitiveType.get())) { + return false; + } + } + } + return true; + } + + @Override + public BoundFunction build(String name, List<?> arguments) { + // use AliasFunction to process TypeCoercion + BoundFunction boundAliasFunction = ((BoundFunction) aliasUdf.withChildren(arguments.stream() + .map(Expression.class::cast).collect(Collectors.toList()))); + + Expression processedExpression = TypeCoercionUtils.processBoundFunction(boundAliasFunction); + List<Expression> inputs = processedExpression.getArguments(); + + Expression boundFunction = FunctionBinder.INSTANCE.rewrite(aliasUdf.getUnboundFunction(), null); Review Comment: i think, maybe u could do this before add udf to avoid to it at every build ########## fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java: ########## @@ -0,0 +1,145 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.udf; + +import org.apache.doris.catalog.AliasFunction; +import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.analyzer.UnboundFunction; +import org.apache.doris.nereids.analyzer.UnboundSlot; +import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.VirtualSlotReference; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.scalar.ScalarFunction; +import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewriter; +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; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * alias function + */ +public class AliasUdf extends ScalarFunction implements ExplicitlyCastableSignature { + private final UnboundFunction unboundFunction; + private final List<String> parameters; + private final List<DataType> argTypes; + private DataType retType; + + /** + * constructor + */ + public AliasUdf(String name, List<DataType> argTypes, UnboundFunction unboundFunction, + List<String> parameters, Expression... arguments) { + super(name, arguments); + this.argTypes = argTypes; + this.unboundFunction = unboundFunction; + this.parameters = parameters; + } + + @Override + public List<FunctionSignature> getSignatures() { + return ImmutableList.of(Suppliers.memoize(() -> FunctionSignature + .of(NullType.INSTANCE, argTypes)).get()); + } + + public List<String> getParameters() { + return parameters; + } + + public UnboundFunction getUnboundFunction() { + return unboundFunction; + } + + public List<DataType> getArgTypes() { + return argTypes; + } + + @Override + public boolean nullable() { + return false; + } + + /** + * translate catalog alias function to nereids alias function + */ + public static void translateToNereidsFunction(String dbName, AliasFunction function) { Review Comment: should not throw any exception outer this function -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org