[feature](array) Add array_last lambda function (#18388)
Add array_last lambda function
This commit is contained in:
@ -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
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
---
|
||||
{
|
||||
"title": "array_last",
|
||||
"language": "en"
|
||||
}
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
## array_last
|
||||
|
||||
<version since="2.0">
|
||||
|
||||
array_last
|
||||
|
||||
</version>
|
||||
|
||||
### description
|
||||
Returns the last element in the array for which func(arr1[i]) returns something other than 0.
|
||||
|
||||
#### Syntax
|
||||
|
||||
```
|
||||
T array_last(lambda, ARRAY<T>)
|
||||
```
|
||||
|
||||
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
|
||||
@ -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"
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
---
|
||||
{
|
||||
"title": "array_last",
|
||||
"language": "zh-CN"
|
||||
}
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
## array_last
|
||||
|
||||
<version since="2.0">
|
||||
|
||||
array_last
|
||||
|
||||
</version>
|
||||
|
||||
### description
|
||||
返回数组中的最后一个func(arr1[i])值不为0的元素。当数组中所有元素进行func(arr1[i])都为0时,结果返回`NULL`值。
|
||||
|
||||
#### Syntax
|
||||
|
||||
```
|
||||
T array_last(lambda, ARRAY<T>)
|
||||
```
|
||||
|
||||
使用一个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
|
||||
@ -35,12 +35,14 @@ import java.util.List;
|
||||
public class LambdaFunctionCallExpr extends FunctionCallExpr {
|
||||
public static final ImmutableSet<String> 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<String> 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<Expr> 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) {
|
||||
|
||||
@ -791,6 +791,7 @@ visible_functions = [
|
||||
|
||||
[['array_zip'], 'ARRAY', ['ARRAY', '...'], ''],
|
||||
|
||||
|
||||
# reverse function for string builtin
|
||||
[['reverse'], 'VARCHAR', ['VARCHAR'], ''],
|
||||
# reverse function support the longtext
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<int(11)> NULL,
|
||||
`c_array2` array<varchar(20)> 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}"
|
||||
}
|
||||
Reference in New Issue
Block a user