diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt
index 98375ab8e0..e88a4072c3 100644
--- a/be/src/vec/CMakeLists.txt
+++ b/be/src/vec/CMakeLists.txt
@@ -177,7 +177,7 @@ set(VEC_FILES
exprs/table_function/vexplode_numbers.cpp
exprs/table_function/vexplode_bitmap.cpp
exprs/lambda_function/varray_map_function.cpp
- exprs/lambda_function/varray_filter_function.cpp
+ exprs/lambda_function/varray_filter_function.cpp
functions/array/function_array_index.cpp
functions/array/function_array_element.cpp
functions/array/function_array_register.cpp
diff --git a/docs/en/docs/sql-manual/sql-functions/array-functions/array_last.md b/docs/en/docs/sql-manual/sql-functions/array-functions/array_last.md
new file mode 100644
index 0000000000..d2931f245e
--- /dev/null
+++ b/docs/en/docs/sql-manual/sql-functions/array-functions/array_last.md
@@ -0,0 +1,71 @@
+---
+{
+ "title": "array_last",
+ "language": "en"
+}
+---
+
+
+
+## array_last
+
+
+
+array_last
+
+
+
+### description
+Returns the last element in the array for which func(arr1[i]) returns something other than 0.
+
+#### Syntax
+
+```
+T array_last(lambda, ARRAY)
+```
+
+Use a lambda bool expression and an array as the input parameters, the lambda expression is used to evaluate the internal data of other input ARRAY parameters.
+
+### notice
+
+`Only supported in vectorized engine`
+
+### example
+
+```
+mysql> select array_last(x->x>2, [1,2,3,0]) ;
++------------------------------------------------------------------------------------------------+
+| array_last(array_filter(ARRAY(1, 2, 3, 0), array_map([x] -> x(0) > 2, ARRAY(1, 2, 3, 0))), -1) |
++------------------------------------------------------------------------------------------------+
+| 3 |
++------------------------------------------------------------------------------------------------+
+
+
+mysql> select array_last(x->x>4, [1,2,3,0]) ;
++------------------------------------------------------------------------------------------------+
+| array_last(array_filter(ARRAY(1, 2, 3, 0), array_map([x] -> x(0) > 4, ARRAY(1, 2, 3, 0))), -1) |
++------------------------------------------------------------------------------------------------+
+| NULL |
++------------------------------------------------------------------------------------------------+
+
+
+### keywords
+
+ARRAY, LAST, ARRAY_LAST
diff --git a/docs/sidebars.json b/docs/sidebars.json
index c543983e05..0bae0ec910 100644
--- a/docs/sidebars.json
+++ b/docs/sidebars.json
@@ -310,6 +310,7 @@
"sql-manual/sql-functions/array-functions/array_cum_sum",
"sql-manual/sql-functions/array-functions/array_exists",
"sql-manual/sql-functions/array-functions/array_first_index",
+ "sql-manual/sql-functions/array-functions/array_last",
"sql-manual/sql-functions/array-functions/arrays_overlap",
"sql-manual/sql-functions/array-functions/countequal",
"sql-manual/sql-functions/array-functions/element_at"
diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_last.md b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_last.md
new file mode 100644
index 0000000000..976430ecc4
--- /dev/null
+++ b/docs/zh-CN/docs/sql-manual/sql-functions/array-functions/array_last.md
@@ -0,0 +1,71 @@
+---
+{
+ "title": "array_last",
+ "language": "zh-CN"
+}
+---
+
+
+
+## array_last
+
+
+
+array_last
+
+
+
+### description
+返回数组中的最后一个func(arr1[i])值不为0的元素。当数组中所有元素进行func(arr1[i])都为0时,结果返回`NULL`值。
+
+#### Syntax
+
+```
+T array_last(lambda, ARRAY)
+```
+
+使用一个lambda表达式和一个ARRAY作为输入参数,lambda表达式为布尔型,用于对ARRAY中的每个元素进行判断返回值。
+
+### notice
+
+`仅支持向量化引擎中使用`
+
+### example
+
+```
+mysql> select array_last(x->x>2, [1,2,3,0]) ;
++------------------------------------------------------------------------------------------------+
+| array_last(array_filter(ARRAY(1, 2, 3, 0), array_map([x] -> x(0) > 2, ARRAY(1, 2, 3, 0))), -1) |
++------------------------------------------------------------------------------------------------+
+| 3 |
++------------------------------------------------------------------------------------------------+
+
+
+mysql> select array_last(x->x>4, [1,2,3,0]) ;
++------------------------------------------------------------------------------------------------+
+| array_last(array_filter(ARRAY(1, 2, 3, 0), array_map([x] -> x(0) > 4, ARRAY(1, 2, 3, 0))), -1) |
++------------------------------------------------------------------------------------------------+
+| NULL |
++------------------------------------------------------------------------------------------------+
+
+
+### keywords
+
+ARRAY, LAST, ARRAY_LAST
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 546ef19822..d31e240b3d 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
@@ -35,12 +35,14 @@ import java.util.List;
public class LambdaFunctionCallExpr extends FunctionCallExpr {
public static final ImmutableSet LAMBDA_FUNCTION_SET = new ImmutableSortedSet.Builder(
String.CASE_INSENSITIVE_ORDER).add("array_map").add("array_filter").add("array_exists").add("array_sortby")
- .add("array_first_index").build();
+ .add("array_first_index").add("array_last").build();
// The functions in this set are all normal array functions when implemented initially.
// and then wants add lambda expr as the input param, so we rewrite it to contains an array_map lambda function
// rather than reimplementing a lambda function, this will be reused the implementation of normal array function
public static final ImmutableSet LAMBDA_MAPPED_FUNCTION_SET = new ImmutableSortedSet.Builder(
- String.CASE_INSENSITIVE_ORDER).add("array_exists").add("array_sortby").add("array_first_index").build();
+ String.CASE_INSENSITIVE_ORDER).add("array_exists").add("array_sortby")
+ .add("array_first_index").add("array_last")
+ .build();
private static final Logger LOG = LogManager.getLogger(LambdaFunctionCallExpr.class);
@@ -204,6 +206,31 @@ public class LambdaFunctionCallExpr extends FunctionCallExpr {
throw new AnalysisException(getFunctionNotFoundError(collectChildReturnTypes()));
}
fn.setReturnType(getChild(0).getType());
+ } else if (fnName.getFunction().equalsIgnoreCase("array_last")) {
+ // array_last(lambda,array)--->array_last(array,lambda)--->element_at(array_filter,-1)
+ if (getChild(childSize - 1) instanceof LambdaFunctionExpr) {
+ List params = new ArrayList<>();
+ for (int i = 0; i <= childSize - 1; ++i) {
+ params.add(getChild(i));
+ }
+ LambdaFunctionCallExpr arrayFilterFunc = new LambdaFunctionCallExpr("array_filter", params);
+ arrayFilterFunc.analyzeImpl(analyzer);
+ IntLiteral indexParam = new IntLiteral(-1, Type.INT);
+
+ argTypes = new Type[2];
+ argTypes[0] = getChild(0).getType();
+ argTypes[1] = indexParam.getType();
+ this.children.clear();
+ this.children.add(arrayFilterFunc);
+ this.children.add(indexParam);
+ }
+ fnName = new FunctionName(null, "element_at");
+ fn = getBuiltinFunction(fnName.getFunction(), argTypes, Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
+ if (fn == null) {
+ LOG.warn("fn element_at not exists");
+ throw new AnalysisException(getFunctionNotFoundError(collectChildReturnTypes()));
+ }
+ fn.setReturnType(((ArrayType) argTypes[0]).getItemType());
}
LOG.info("fn string: " + fn.signatureString() + ". return type: " + fn.getReturnType());
if (fn == null) {
diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py
index 6a302432c8..f019b4f97b 100644
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -791,6 +791,7 @@ visible_functions = [
[['array_zip'], 'ARRAY', ['ARRAY', '...'], ''],
+
# reverse function for string builtin
[['reverse'], 'VARCHAR', ['VARCHAR'], ''],
# reverse function support the longtext
diff --git a/regression-test/data/query_p0/sql_functions/array_functions/test_array_last.out b/regression-test/data/query_p0/sql_functions/array_functions/test_array_last.out
new file mode 100644
index 0000000000..5905303382
--- /dev/null
+++ b/regression-test/data/query_p0/sql_functions/array_functions/test_array_last.out
@@ -0,0 +1,28 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !select_00 --
+5
+
+-- !select_01 --
+\N
+
+-- !select_03 --
+5
+
+-- !select_04 --
+c
+
+-- !select_05 --
+5.300000000
+
+-- !select_06 --
+0 [2] ['123', '124', '125']
+1 [1, 2, 3, 4, 5] ['234', '124', '125']
+2 [1, 2, 10, 12, 10] ['345', '234', '123']
+3 [1, 3, 4, 2] ['222', '444', '555']
+
+-- !select_07 --
+\N 125
+5 125
+10 234
+4 555
+
diff --git a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_last.groovy b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_last.groovy
new file mode 100644
index 0000000000..fe5fdec9ff
--- /dev/null
+++ b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_last.groovy
@@ -0,0 +1,53 @@
+// 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("test_array_last") {
+
+ def tableName = "test_array_last"
+ sql "DROP TABLE IF EXISTS ${tableName}"
+ sql """
+ CREATE TABLE IF NOT EXISTS `${tableName}` (
+ `id` int(11) NULL,
+ `c_array1` array NULL,
+ `c_array2` array NULL
+ ) ENGINE=OLAP
+ DUPLICATE KEY(`id`)
+ DISTRIBUTED BY HASH(`id`) BUCKETS 1
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1",
+ "storage_format" = "V2"
+ )
+ """
+
+
+ sql """INSERT INTO ${tableName} values
+ (0, [2], ['123', '124', '125']),
+ (1, [1,2,3,4,5], ['234', '124', '125']),
+ (2, [1,2,10,12,10], ['345', '234', '123']),
+ (3, [1,3,4,2], ['222', '444', '555'])
+ """
+ qt_select_00 " select array_last(x -> x>3, [1,2,3,4,5]);"
+ qt_select_01 " select array_last(x -> x<1, [1,2,3,4,5]);"
+ qt_select_03 " select array_last(x -> x>=5,[1,2,3,4,5]);"
+ qt_select_04 " select array_last(x -> x > 'abc', ['a','b','c']);"
+ qt_select_05 " select array_last(x -> x > 5.2 , [10.2, 5.3, 4]);"
+
+ qt_select_06 "select * from ${tableName} order by id;"
+
+ qt_select_07 " select array_last(x->x>3,c_array1), array_last(x-> x>'124',c_array2) from test_array_last order by id;"
+ sql "DROP TABLE IF EXISTS ${tableName}"
+}
\ No newline at end of file