This is an automated email from the ASF dual-hosted git repository. morrysnow pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new 5b590bbfcf [feat](Nereids) add lambda func array_last and array_first (#24682) 5b590bbfcf is described below commit 5b590bbfcf13cee5a868093eca58606c22845e13 Author: 谢健 <jianx...@gmail.com> AuthorDate: Thu Sep 21 12:23:34 2023 +0800 [feat](Nereids) add lambda func array_last and array_first (#24682) --- .../doris/analysis/LambdaFunctionCallExpr.java | 1 + .../doris/catalog/BuiltinScalarFunctions.java | 4 + .../glue/translator/ExpressionTranslator.java | 22 +- .../expressions/functions/scalar/ArrayFirst.java | 49 +++ .../expressions/functions/scalar/ArrayLast.java | 49 +++ .../nereids_function_p0/scalar_function/Array.out | 464 +++++++++++++++++++++ .../scalar_function/Array.groovy | 34 ++ 7 files changed, 611 insertions(+), 12 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java index c8b0cbc9ab..c247b071a0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java @@ -45,6 +45,7 @@ public class LambdaFunctionCallExpr extends FunctionCallExpr { public static final ImmutableSet<String> LAMBDA_MAPPED_FUNCTION_SET = new ImmutableSortedSet.Builder( String.CASE_INSENSITIVE_ORDER).add("array_exists").add("array_sortby") .add("array_first_index").add("array_last_index").add("array_first").add("array_last").add("array_count") + .add("element_at") .build(); private static final Logger LOG = LogManager.getLogger(LambdaFunctionCallExpr.class); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java index 37f534d770..6608fd8ea2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java @@ -36,9 +36,11 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayEnumerat import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayExcept; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayExists; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayFilter; +import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayFirst; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayFirstIndex; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayIntersect; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayJoin; +import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayLast; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayLastIndex; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayMap; import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayMax; @@ -413,9 +415,11 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(ArrayExcept.class, "array_except"), scalar(ArrayExists.class, "array_exists"), scalar(ArrayFilter.class, "array_filter"), + scalar(ArrayFirst.class, "array_first"), scalar(ArrayFirstIndex.class, "array_first_index"), scalar(ArrayIntersect.class, "array_intersect"), scalar(ArrayJoin.class, "array_join"), + scalar(ArrayLast.class, "array_last"), scalar(ArrayLastIndex.class, "array_last_index"), scalar(ArrayMap.class, "array_map"), scalar(ArrayMax.class, "array_max"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/ExpressionTranslator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/ExpressionTranslator.java index d2a16c29b8..872c7eed5c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/ExpressionTranslator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/ExpressionTranslator.java @@ -87,6 +87,8 @@ import org.apache.doris.nereids.trees.expressions.functions.combinator.MergeComb import org.apache.doris.nereids.trees.expressions.functions.combinator.StateCombinator; import org.apache.doris.nereids.trees.expressions.functions.combinator.UnionCombinator; import org.apache.doris.nereids.trees.expressions.functions.generator.TableGeneratingFunction; +import org.apache.doris.nereids.trees.expressions.functions.scalar.ArrayMap; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HighOrderFunction; import org.apache.doris.nereids.trees.expressions.functions.scalar.Lambda; import org.apache.doris.nereids.trees.expressions.functions.scalar.ScalarFunction; import org.apache.doris.nereids.trees.expressions.functions.udf.JavaUdaf; @@ -405,9 +407,10 @@ public class ExpressionTranslator extends DefaultExpressionVisitor<Expr, PlanTra return new LambdaFunctionExpr(func, lambda.getLambdaArgumentNames(), arguments); } - private Expr visitHighOrderFunction(ScalarFunction function, PlanTranslatorContext context) { - Lambda lambda = (Lambda) function.child(0); - List<Expr> arguments = new ArrayList<>(function.children().size()); + @Override + public Expr visitArrayMap(ArrayMap arrayMap, PlanTranslatorContext context) { + Lambda lambda = (Lambda) arrayMap.child(0); + List<Expr> arguments = new ArrayList<>(arrayMap.children().size()); arguments.add(null); int columnId = 0; for (ArrayItemReference arrayItemReference : lambda.getLambdaArguments()) { @@ -424,7 +427,7 @@ public class ExpressionTranslator extends DefaultExpressionVisitor<Expr, PlanTra columnId += 1; } - List<Type> argTypes = function.getArguments().stream() + List<Type> argTypes = arrayMap.getArguments().stream() .map(Expression::getDataType) .map(DataType::toCatalogDataType) .collect(Collectors.toList()); @@ -433,11 +436,11 @@ public class ExpressionTranslator extends DefaultExpressionVisitor<Expr, PlanTra .map(Expression::getDataType) .map(DataType::toCatalogDataType) .forEach(argTypes::add); - NullableMode nullableMode = function.nullable() + NullableMode nullableMode = arrayMap.nullable() ? NullableMode.ALWAYS_NULLABLE : NullableMode.ALWAYS_NOT_NULLABLE; org.apache.doris.catalog.Function catalogFunction = new Function( - new FunctionName(function.getName()), argTypes, + new FunctionName(arrayMap.getName()), argTypes, ArrayType.create(lambda.getRetType().toCatalogDataType(), true), true, true, nullableMode); @@ -449,10 +452,6 @@ public class ExpressionTranslator extends DefaultExpressionVisitor<Expr, PlanTra @Override public Expr visitScalarFunction(ScalarFunction function, PlanTranslatorContext context) { - if (function.isHighOrder()) { - return visitHighOrderFunction(function, context); - } - List<Expr> arguments = function.getArguments().stream() .map(arg -> arg.accept(this, context)) .collect(Collectors.toList()); @@ -472,8 +471,7 @@ public class ExpressionTranslator extends DefaultExpressionVisitor<Expr, PlanTra "", TFunctionBinaryType.BUILTIN, true, true, nullableMode); // create catalog FunctionCallExpr without analyze again - if (LambdaFunctionCallExpr.LAMBDA_FUNCTION_SET.contains(function.getName()) - || LambdaFunctionCallExpr.LAMBDA_MAPPED_FUNCTION_SET.contains(function.getName())) { + if (function instanceof HighOrderFunction) { return new LambdaFunctionCallExpr(catalogFunction, new FunctionParams(false, arguments)); } return new FunctionCallExpr(catalogFunction, new FunctionParams(false, arguments)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayFirst.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayFirst.java new file mode 100644 index 0000000000..8563a3e455 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayFirst.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.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; + +import java.util.List; + +/** + * ScalarFunction 'array_first'. + */ +public class ArrayFirst extends ElementAt + implements HighOrderFunction { + + /** + * constructor with arguments. + * array_first(lambda, a1, ...) = element_at(array_filter(lambda, a1, ...), 1) + */ + public ArrayFirst(Expression arg) { + super(new ArrayFilter(arg), new BigIntLiteral(1)); + if (!(arg instanceof Lambda)) { + throw new AnalysisException( + String.format("The 1st arg of %s must be lambda but is %s", getName(), arg)); + } + } + + @Override + public List<FunctionSignature> getImplSignature() { + return SIGNATURES; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayLast.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayLast.java new file mode 100644 index 0000000000..71466614e3 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/ArrayLast.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.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; + +import java.util.List; + +/** + * ScalarFunction 'array_last'. + */ +public class ArrayLast extends ElementAt + implements HighOrderFunction { + + /** + * constructor with arguments. + * array_last(lambda, a1, ...) = element_at(array_filter(lambda, a1, ...), -1) + */ + public ArrayLast(Expression arg) { + super(new ArrayFilter(arg), new BigIntLiteral(-1)); + if (!(arg instanceof Lambda)) { + throw new AnalysisException( + String.format("The 1st arg of %s must be lambda but is %s", getName(), arg)); + } + } + + @Override + public List<FunctionSignature> getImplSignature() { + return SIGNATURES; + } +} diff --git a/regression-test/data/nereids_function_p0/scalar_function/Array.out b/regression-test/data/nereids_function_p0/scalar_function/Array.out index a0a2b958e9..21da869c4c 100644 --- a/regression-test/data/nereids_function_p0/scalar_function/Array.out +++ b/regression-test/data/nereids_function_p0/scalar_function/Array.out @@ -11570,3 +11570,467 @@ true 2 2 +-- !sql_array_first_Double -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.1 +1.2 + +-- !sql_array_first_Double_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.1 +1.2 + +-- !sql_array_first_Float -- +\N +\N +10.0 +11.0 +12.0 +2.0 +3.0 +4.0 +5.0 +6.0 +7.0 +8.0 +9.0 + +-- !sql_array_first_Float_notnull -- +\N +10.0 +11.0 +12.0 +2.0 +3.0 +4.0 +5.0 +6.0 +7.0 +8.0 +9.0 + +-- !sql_array_first_LargeInt -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_LargeInt_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_BigInt -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_BigInt_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_SmallInt -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_SmallInt_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_Integer -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_Integer_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_first_TinyInt -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !sql_array_first_TinyInt_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !sql_array_first_DecimalV3 -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.100000000 +1.200000000 + +-- !sql_array_first_DecimalV3_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.100000000 +1.200000000 + +-- !sql_array_last_Double -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.1 +1.2 + +-- !sql_array_last_Double_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.1 +1.2 + +-- !sql_array_last_Float -- +\N +\N +10.0 +11.0 +12.0 +2.0 +3.0 +4.0 +5.0 +6.0 +7.0 +8.0 +9.0 + +-- !sql_array_last_Float_notnull -- +\N +10.0 +11.0 +12.0 +2.0 +3.0 +4.0 +5.0 +6.0 +7.0 +8.0 +9.0 + +-- !sql_array_last_LargeInt -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_LargeInt_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_BigInt -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_BigInt_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_SmallInt -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_SmallInt_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_Integer -- +\N +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_Integer_notnull -- +\N +10 +11 +12 +2 +3 +4 +5 +6 +7 +8 +9 + +-- !sql_array_last_TinyInt -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !sql_array_last_TinyInt_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N + +-- !sql_array_last_DecimalV3 -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.100000000 +1.200000000 + +-- !sql_array_last_DecimalV3_notnull -- +\N +\N +\N +\N +\N +\N +\N +\N +\N +\N +1.100000000 +1.200000000 + diff --git a/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy b/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy index a02e324778..3b99b2dd18 100644 --- a/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy +++ b/regression-test/suites/nereids_function_p0/scalar_function/Array.groovy @@ -961,6 +961,40 @@ suite("nereids_scalar_fn_Array") { order_qt_sql_array_last_index_TinyInt_notnull "select array_last_index(x -> x > 1, katint) from fn_test_not_nullable" order_qt_sql_array_last_index_DecimalV3 "select array_last_index(x -> x > 1, kadcml) from fn_test" order_qt_sql_array_last_index_DecimalV3_notnull "select array_last_index(x -> x > 1, kadcml) from fn_test_not_nullable" + order_qt_sql_array_first_Double "select array_first(x -> x > 1, kadbl) from fn_test" + // test array_first + order_qt_sql_array_first_Double_notnull "select array_first(x -> x > 1, kadbl) from fn_test_not_nullable" + order_qt_sql_array_first_Float "select array_first(x -> x > 1, kafloat) from fn_test" + order_qt_sql_array_first_Float_notnull "select array_first(x -> x > 1, kafloat) from fn_test_not_nullable" + order_qt_sql_array_first_LargeInt "select array_first(x -> x > 1, kalint) from fn_test" + order_qt_sql_array_first_LargeInt_notnull "select array_first(x -> x > 1, kalint) from fn_test_not_nullable" + order_qt_sql_array_first_BigInt "select array_first(x -> x > 1, kabint) from fn_test" + order_qt_sql_array_first_BigInt_notnull "select array_first(x -> x > 1, kabint) from fn_test_not_nullable" + order_qt_sql_array_first_SmallInt "select array_first(x -> x > 1, kasint) from fn_test" + order_qt_sql_array_first_SmallInt_notnull "select array_first(x -> x > 1, kasint) from fn_test_not_nullable" + order_qt_sql_array_first_Integer "select array_first(x -> x > 1, kaint) from fn_test" + order_qt_sql_array_first_Integer_notnull "select array_first(x -> x > 1, kaint) from fn_test_not_nullable" + order_qt_sql_array_first_TinyInt "select array_first(x -> x > 1, katint) from fn_test" + order_qt_sql_array_first_TinyInt_notnull "select array_first(x -> x > 1, katint) from fn_test_not_nullable" + order_qt_sql_array_first_DecimalV3 "select array_first(x -> x > 1, kadcml) from fn_test" + order_qt_sql_array_first_DecimalV3_notnull "select array_first(x -> x > 1, kadcml) from fn_test_not_nullable" + // test array_last + order_qt_sql_array_last_Double "select array_last(x -> x > 1, kadbl) from fn_test" + order_qt_sql_array_last_Double_notnull "select array_last(x -> x > 1, kadbl) from fn_test_not_nullable" + order_qt_sql_array_last_Float "select array_last(x -> x > 1, kafloat) from fn_test" + order_qt_sql_array_last_Float_notnull "select array_last(x -> x > 1, kafloat) from fn_test_not_nullable" + order_qt_sql_array_last_LargeInt "select array_last(x -> x > 1, kalint) from fn_test" + order_qt_sql_array_last_LargeInt_notnull "select array_last(x -> x > 1, kalint) from fn_test_not_nullable" + order_qt_sql_array_last_BigInt "select array_last(x -> x > 1, kabint) from fn_test" + order_qt_sql_array_last_BigInt_notnull "select array_last(x -> x > 1, kabint) from fn_test_not_nullable" + order_qt_sql_array_last_SmallInt "select array_last(x -> x > 1, kasint) from fn_test" + order_qt_sql_array_last_SmallInt_notnull "select array_last(x -> x > 1, kasint) from fn_test_not_nullable" + order_qt_sql_array_last_Integer "select array_last(x -> x > 1, kaint) from fn_test" + order_qt_sql_array_last_Integer_notnull "select array_last(x -> x > 1, kaint) from fn_test_not_nullable" + order_qt_sql_array_last_TinyInt "select array_last(x -> x > 1, katint) from fn_test" + order_qt_sql_array_last_TinyInt_notnull "select array_last(x -> x > 1, katint) from fn_test_not_nullable" + order_qt_sql_array_last_DecimalV3 "select array_last(x -> x > 1, kadcml) from fn_test" + order_qt_sql_array_last_DecimalV3_notnull "select array_last(x -> x > 1, kadcml) from fn_test_not_nullable" test { sql "select tokenize('arg1','xxx = yyy,zzz');" --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org