[vectorized](function) support array_exists lambda function (#17931)

Co-authored-by: zhangyu209 <zhangyu209@meituan.com>
This commit is contained in:
ZhangYu0123
2023-03-23 11:11:39 +08:00
committed by GitHub
parent 994a2e967b
commit 089a91ecd5
11 changed files with 537 additions and 4 deletions

View File

@ -174,6 +174,7 @@ set(VEC_FILES
functions/array/function_array_remove.cpp
functions/array/function_array_union.cpp
functions/array/function_array_except.cpp
functions/array/function_array_exists.cpp
functions/array/function_array_intersect.cpp
functions/array/function_array_slice.cpp
functions/array/function_array_difference.cpp

View File

@ -0,0 +1,90 @@
// 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.
#include <vec/columns/column_array.h>
#include <vec/columns/column_nullable.h>
#include <vec/columns/columns_number.h>
#include <vec/data_types/data_type_array.h>
#include <vec/data_types/data_type_number.h>
#include <vec/functions/function.h>
#include <vec/functions/function_helpers.h>
#include <vec/functions/simple_function_factory.h>
#include <vec/utils/util.hpp>
namespace doris::vectorized {
// array_exists([1, 2, 3, 0]) -> [1, 1, 1, 0]
class FunctionArrayExists : public IFunction {
public:
static constexpr auto name = "array_exists";
static FunctionPtr create() { return std::make_shared<FunctionArrayExists>(); }
String get_name() const override { return name; }
size_t get_number_of_arguments() const override { return 1; }
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
DCHECK(is_array(arguments[0]))
<< "first argument for function: " << name << " should be DataTypeArray"
<< " and arguments[0] is " << arguments[0]->get_name();
return arguments[0];
}
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
size_t result, size_t input_rows_count) override {
// 1. get first array column
const auto first_column =
block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
const ColumnArray& first_col_array = assert_cast<const ColumnArray&>(*first_column);
const auto& first_off_data = assert_cast<const ColumnArray::ColumnOffsets&>(
first_col_array.get_offsets_column());
const auto& nested_nullable_column =
assert_cast<const ColumnNullable&>(*first_col_array.get_data_ptr());
const auto nested_column = nested_nullable_column.get_nested_column_ptr();
const size_t nested_column_size = nested_column->size();
MutableColumnPtr result_null_map =
nested_nullable_column.get_null_map_column_ptr()->clone_resized(nested_column_size);
// 2. compute result
MutableColumnPtr result_column = ColumnUInt8::create(nested_column_size, 0);
auto* __restrict result_column_data =
assert_cast<ColumnUInt8&>(*result_column).get_data().data();
MutableColumnPtr result_offset_column = first_off_data.clone_resized(first_off_data.size());
const auto* __restrict nested_column_data =
assert_cast<const ColumnUInt8&>(*nested_column).get_data().data();
for (size_t row = 0; row < nested_column_size; ++row) {
result_column_data[row] = nested_column_data[row] != 0;
}
ColumnPtr result_nullalble_column =
ColumnNullable::create(std::move(result_column), std::move(result_null_map));
ColumnPtr column_array =
ColumnArray::create(result_nullalble_column, std::move(result_offset_column));
block.replace_by_position(result, column_array);
return Status::OK();
}
};
void register_function_array_exists(SimpleFunctionFactory& factory) {
factory.register_function<FunctionArrayExists>();
}
} // namespace doris::vectorized

View File

@ -22,6 +22,7 @@
namespace doris::vectorized {
void register_function_array_exists(SimpleFunctionFactory&);
void register_function_array_element(SimpleFunctionFactory&);
void register_function_array_index(SimpleFunctionFactory&);
void register_function_array_size(SimpleFunctionFactory&);
@ -49,6 +50,7 @@ void register_function_array_zip(SimpleFunctionFactory&);
void register_function_array_pushfront(SimpleFunctionFactory& factory);
void register_function_array(SimpleFunctionFactory& factory) {
register_function_array_exists(factory);
register_function_array_element(factory);
register_function_array_index(factory);
register_function_array_size(factory);

View File

@ -0,0 +1,114 @@
---
{
"title": "array_exists",
"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_exists
<version since="2.0">
array_exists(lambda,array1,array2....)
array_exists(array1)
</version>
### description
Use an optional lambda expression as an input parameter to perform corresponding expression calculations on the internal data of other input ARRAY parameters. Returns 1 when the calculation returns something other than 0; otherwise returns 0.
There are one or more parameters input in the lambda expression, which must be consistent with the number of input array columns later. Legal scalar functions can be executed in lambda, aggregate functions, etc. are not supported.
When lambda expression is not used as a parameter, array1 is used as the calculation result.
```
array_exists(x->x, array1);
array_exists(x->(x%2 = 0), array1);
array_exists(x->(abs(x)-1), array1);
array_exists((x,y)->(x = y), array1, array2);
array_exists(array1);
```
### example
```sql
mysql [test]>select *, array_exists(x->x>1,[1,2,3]) from array_test2 order by id;
+------+-----------------+-------------------------+-----------------------------------------------+
| id | c_array1 | c_array2 | array_exists([x] -> x(0) > 1, ARRAY(1, 2, 3)) |
+------+-----------------+-------------------------+-----------------------------------------------+
| 1 | [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 1, 1] |
| 2 | [6, 7, 8] | [10, 12, 13] | [0, 1, 1] |
| 3 | [1] | [-100] | [0, 1, 1] |
| 4 | NULL | NULL | [0, 1, 1] |
+------+-----------------+-------------------------+-----------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select c_array1, c_array2, array_exists(x->x%2=0,[1,2,3]) from array_test2 order by id;
+-----------------+-------------------------+---------------------------------------------------+
| c_array1 | c_array2 | array_exists([x] -> x(0) % 2 = 0, ARRAY(1, 2, 3)) |
+-----------------+-------------------------+---------------------------------------------------+
| [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 1, 0] |
| [6, 7, 8] | [10, 12, 13] | [0, 1, 0] |
| [1] | [-100] | [0, 1, 0] |
| NULL | NULL | [0, 1, 0] |
+-----------------+-------------------------+---------------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select c_array1, c_array2, array_exists(x->abs(x)-1,[1,2,3]) from array_test2 order by id;
+-----------------+-------------------------+----------------------------------------------------+
| c_array1 | c_array2 | array_exists([x] -> abs(x(0)) - 1, ARRAY(1, 2, 3)) |
+-----------------+-------------------------+----------------------------------------------------+
| [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 1, 1, 1, 1] |
| [6, 7, 8] | [10, 12, 13] | [1, 1, 1] |
| [1, NULL] | [-100] | [0, NULL] |
| NULL | NULL | NULL |
+-----------------+-------------------------+----------------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select c_array1, c_array2, array_exists((x,y)->x>y,c_array1,c_array2) from array_test2 order by id;
+-----------------+-------------------------+-------------------------------------------------------------+
| c_array1 | c_array2 | array_exists([x, y] -> x(0) > y(1), `c_array1`, `c_array2`) |
+-----------------+-------------------------+-------------------------------------------------------------+
| [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 0, 1, 0, 1] |
| [6, 7, 8] | [10, 12, 13] | [0, 0, 0] |
| [1] | [-100] | [1] |
| NULL | NULL | NULL |
+-----------------+-------------------------+-------------------------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select *, array_exists(c_array1) from array_test2 order by id;
+------+-----------------+-------------------------+--------------------------+
| id | c_array1 | c_array2 | array_exists(`c_array1`) |
+------+-----------------+-------------------------+--------------------------+
| 1 | [1, 2, 3, 0, 5] | [10, 20, -40, 80, -100] | [1, 1, 1, 0, 1] |
| 2 | [6, 7, 8] | [10, 12, 13] | [1, 1, 1] |
| 3 | [0, NULL] | [-100] | [0, NULL] |
| 4 | NULL | NULL | NULL |
+------+-----------------+-------------------------+--------------------------+
4 rows in set (0.02 sec)
```
### keywords
ARRAY,ARRAY_EXISTS

View File

@ -301,6 +301,7 @@
"sql-manual/sql-functions/array-functions/array_compact",
"sql-manual/sql-functions/array-functions/array_concat",
"sql-manual/sql-functions/array-functions/array_zip",
"sql-manual/sql-functions/array-functions/array_exists",
"sql-manual/sql-functions/array-functions/arrays_overlap",
"sql-manual/sql-functions/array-functions/countequal",
"sql-manual/sql-functions/array-functions/element_at"

View File

@ -0,0 +1,113 @@
---
{
"title": "array_exists",
"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_exists
<version since="2.0">
array_exists(lambda,array1,array2....)
array_exists(array1)
</version>
### description
使用一个可选lambda表达式作为输入参数,对其他的输入ARRAY参数的内部数据做对应表达式计算。当计算返回非0时,返回1;否则返回0。
在lambda表达式中输入的参数为1个或多个,必须和后面的输入array列数量一致。在lambda中可以执行合法的标量函数,不支持聚合函数等。
在没有使用lambda作为参数时,array1作为计算结果。
```
array_exists(x->x, array1);
array_exists(x->(x%2 = 0), array1);
array_exists(x->(abs(x)-1), array1);
array_exists((x,y)->(x = y), array1, array2);
array_exists(array1);
```
### example
```sql
mysql [test]>select *, array_exists(x->x>1,[1,2,3]) from array_test2 order by id;
+------+-----------------+-------------------------+-----------------------------------------------+
| id | c_array1 | c_array2 | array_exists([x] -> x(0) > 1, ARRAY(1, 2, 3)) |
+------+-----------------+-------------------------+-----------------------------------------------+
| 1 | [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 1, 1] |
| 2 | [6, 7, 8] | [10, 12, 13] | [0, 1, 1] |
| 3 | [1] | [-100] | [0, 1, 1] |
| 4 | NULL | NULL | [0, 1, 1] |
+------+-----------------+-------------------------+-----------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select c_array1, c_array2, array_exists(x->x%2=0,[1,2,3]) from array_test2 order by id;
+-----------------+-------------------------+---------------------------------------------------+
| c_array1 | c_array2 | array_exists([x] -> x(0) % 2 = 0, ARRAY(1, 2, 3)) |
+-----------------+-------------------------+---------------------------------------------------+
| [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 1, 0] |
| [6, 7, 8] | [10, 12, 13] | [0, 1, 0] |
| [1] | [-100] | [0, 1, 0] |
| NULL | NULL | [0, 1, 0] |
+-----------------+-------------------------+---------------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select c_array1, c_array2, array_exists(x->abs(x)-1,[1,2,3]) from array_test2 order by id;
+-----------------+-------------------------+----------------------------------------------------+
| c_array1 | c_array2 | array_exists([x] -> abs(x(0)) - 1, ARRAY(1, 2, 3)) |
+-----------------+-------------------------+----------------------------------------------------+
| [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 1, 1, 1, 1] |
| [6, 7, 8] | [10, 12, 13] | [1, 1, 1] |
| [1, NULL] | [-100] | [0, NULL] |
| NULL | NULL | NULL |
+-----------------+-------------------------+----------------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select c_array1, c_array2, array_exists((x,y)->x>y,c_array1,c_array2) from array_test2 order by id;
+-----------------+-------------------------+-------------------------------------------------------------+
| c_array1 | c_array2 | array_exists([x, y] -> x(0) > y(1), `c_array1`, `c_array2`) |
+-----------------+-------------------------+-------------------------------------------------------------+
| [1, 2, 3, 4, 5] | [10, 20, -40, 80, -100] | [0, 0, 1, 0, 1] |
| [6, 7, 8] | [10, 12, 13] | [0, 0, 0] |
| [1] | [-100] | [1] |
| NULL | NULL | NULL |
+-----------------+-------------------------+-------------------------------------------------------------+
4 rows in set (0.02 sec)
mysql [test]>select *, array_exists(c_array1) from array_test2 order by id;
+------+-----------------+-------------------------+--------------------------+
| id | c_array1 | c_array2 | array_exists(`c_array1`) |
+------+-----------------+-------------------------+--------------------------+
| 1 | [1, 2, 3, 0, 5] | [10, 20, -40, 80, -100] | [1, 1, 1, 0, 1] |
| 2 | [6, 7, 8] | [10, 12, 13] | [1, 1, 1] |
| 3 | [0, NULL] | [-100] | [0, NULL] |
| 4 | NULL | NULL | NULL |
+------+-----------------+-------------------------+--------------------------+
4 rows in set (0.02 sec)
```
### keywords
ARRAY,ARRAY_EXISTS

View File

@ -1047,6 +1047,23 @@ public class FunctionCallExpr extends Expr {
uncheckedCastChild(compatibleType, i);
}
}
if (fnName.getFunction().equalsIgnoreCase("array_exists")) {
Type[] newArgTypes = new Type[1];
if (!(getChild(0) instanceof CastExpr)) {
Expr castExpr = getChild(0).castTo(ArrayType.create(Type.BOOLEAN, true));
this.setChild(0, castExpr);
newArgTypes[0] = castExpr.getType();
}
fn = getBuiltinFunction(fnName.getFunction(), newArgTypes,
Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
if (fn == null) {
LOG.warn("fn {} not exists", this.toSqlImpl());
throw new AnalysisException(getFunctionNotFoundError(collectChildReturnTypes()));
}
fn.setReturnType(getChild(0).getType());
}
}
// Provide better error message for some aggregate builtins. These can be

View File

@ -34,7 +34,10 @@ 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").build();
String.CASE_INSENSITIVE_ORDER).add("array_map").add("array_filter").add("array_exists").build();
public static final ImmutableSet<String> LAMBDA_MAPPED_FUNCTION_SET = new ImmutableSortedSet.Builder(
String.CASE_INSENSITIVE_ORDER).add("array_exists").build();
private static final Logger LOG = LogManager.getLogger(LambdaFunctionCallExpr.class);
@ -97,8 +100,41 @@ public class LambdaFunctionCallExpr extends FunctionCallExpr {
throw new AnalysisException(getFunctionNotFoundError(collectChildReturnTypes()));
}
fn.setReturnType(ArrayType.create(lambda.getChild(0).getType(), true));
}
if (fnName.getFunction().equalsIgnoreCase("array_filter")) {
} else if (fnName.getFunction().equalsIgnoreCase("array_exists")) {
if (fnParams.exprs() == null || fnParams.exprs().size() < 1) {
throw new AnalysisException("The " + fnName.getFunction() + " function must have at least two params");
}
// array_exists(x->x>3, [1,2,3,6,34,3,11])
// ---> array_exists(array_map(x->x>3, [1,2,3,6,34,3,11]))
Type[] newArgTypes = new Type[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 arrayMapFunc = new LambdaFunctionCallExpr("array_map",
params);
arrayMapFunc.analyzeImpl(analyzer);
Expr castExpr = arrayMapFunc.castTo(ArrayType.create(Type.BOOLEAN, true));
this.clearChildren();
this.addChild(castExpr);
newArgTypes[0] = castExpr.getType();
}
if (!(getChild(0) instanceof CastExpr)) {
Expr castExpr = getChild(0).castTo(ArrayType.create(Type.BOOLEAN, true));
this.setChild(0, castExpr);
newArgTypes[0] = castExpr.getType();
}
fn = getBuiltinFunction(fnName.getFunction(), newArgTypes,
Function.CompareMode.IS_NONSTRICT_SUPERTYPE_OF);
if (fn == null) {
LOG.warn("fn {} not exists", this.toSqlImpl());
throw new AnalysisException(getFunctionNotFoundError(collectChildReturnTypes()));
}
fn.setReturnType(getChild(0).getType());
} else if (fnName.getFunction().equalsIgnoreCase("array_filter")) {
if (fnParams.exprs() == null || fnParams.exprs().size() != 2) {
throw new AnalysisException("The " + fnName.getFunction() + " function must have at least two params");
}
@ -139,6 +175,11 @@ public class LambdaFunctionCallExpr extends FunctionCallExpr {
@Override
protected void toThrift(TExprNode msg) {
msg.node_type = TExprNodeType.LAMBDA_FUNCTION_CALL_EXPR;
FunctionName fnName = getFnName();
if (LAMBDA_MAPPED_FUNCTION_SET.contains(fnName.getFunction().toLowerCase())) {
msg.node_type = TExprNodeType.FUNCTION_CALL;
} else {
msg.node_type = TExprNodeType.LAMBDA_FUNCTION_CALL_EXPR;
}
}
}

View File

@ -612,6 +612,25 @@ visible_functions = [
[['array_filter'], 'ARRAY_DATETIMEV2',['ARRAY_DATETIMEV2', 'ARRAY_BOOLEAN'], ''],
[['array_filter'], 'ARRAY_DATEV2',['ARRAY_DATEV2', 'ARRAY_BOOLEAN'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_BOOLEAN'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_TINYINT'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_SMALLINT'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_INT'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_BIGINT'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_LARGEINT'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DATETIME'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DATE'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DATETIMEV2'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DATEV2'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_FLOAT'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DOUBLE'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DECIMALV2'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DECIMAL32'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DECIMAL64'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_DECIMAL128'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_VARCHAR'], ''],
[['array_exists'], 'ARRAY_BOOLEAN', ['ARRAY_STRING'], ''],
[['array_pushfront'], 'ARRAY_BOOLEAN', ['ARRAY_BOOLEAN', 'BOOLEAN'], 'ALWAYS_NULLABLE'],
[['array_pushfront'], 'ARRAY_TINYINT', ['ARRAY_TINYINT', 'TINYINT'], 'ALWAYS_NULLABLE'],
[['array_pushfront'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'SMALLINT'], 'ALWAYS_NULLABLE'],

View File

@ -0,0 +1,72 @@
-- This file is automatically generated. You should know what you did if you want to edit this
-- !select_1 --
1 [1, 2, 3, 4, 5] [10, 20, -40, 80, -100]
2 [6, 7, 8] [10, 12, 13]
3 [1] [-100]
4 \N \N
-- !select_2 --
1 [1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [0, 0, 1]
2 [6, 7, 8] [10, 12, 13] [0, 0, 1]
3 [1] [-100] [0, 0, 1]
4 \N \N [0, 0, 1]
-- !select_3 --
1 [1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [1, 1, 1]
2 [6, 7, 8] [10, 12, 13] [1, 1, 1]
3 [1] [-100] [1, 1, 1]
4 \N \N [1, 1, 1]
-- !select_4 --
[1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [0, 1, 0]
[6, 7, 8] [10, 12, 13] [0, 1, 0]
[1] [-100] [0, 1, 0]
\N \N [0, 1, 0]
-- !select_5 --
[1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [1, 1, 1, 1, 1]
[6, 7, 8] [10, 12, 13] [1, 1, 1]
[1] [-100] [1]
\N \N \N
-- !select_6 --
[1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [1, 1, 1, 1, 1]
[6, 7, 8] [10, 12, 13] [1, 1, 1]
[1] [-100] [1]
\N \N \N
-- !select_7 --
[1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [0, 0, 0, 1, 1]
[6, 7, 8] [10, 12, 13] [1, 1, 1]
[1] [-100] [0]
\N \N \N
-- !select_8 --
[]
-- !select_9 --
[NULL]
-- !select_10 --
[1, 0]
-- !select_11 --
[1, 0, 0]
-- !select_12 --
1 [1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [1, 1, 1]
2 [6, 7, 8] [10, 12, 13] [1, 1, 1]
3 [1] [-100] [1, 1, 1]
4 \N \N [1, 1, 1]
-- !select_13 --
[1, 2, 3, 4, 5] [10, 20, -40, 80, -100] [1, 1, 1, 1, 1]
[6, 7, 8] [10, 12, 13] [1, 1, 1]
[1] [-100] [1]
\N \N \N
-- !select_14 --
[]
-- !select_15 --
[NULL, 1, 1]

View File

@ -0,0 +1,63 @@
// 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_exists_function") {
def tableName = "array_exists_table"
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<int(11)> 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
(1, [1,2,3,4,5], [10,20,-40,80,-100]),
(2, [6,7,8],[10,12,13]), (3, [1],[-100]), (4, null,null)
"""
qt_select_1 "select * from ${tableName} order by id;"
qt_select_2 "select *, array_exists(x->x>2,[1,2,3]) from ${tableName} order by id;"
qt_select_3 "select *, array_exists(x->x+1,[1,2,3]) from ${tableName} order by id;"
qt_select_4 "select c_array1, c_array2, array_exists(x->x%2=0,[1,2,3]) from ${tableName} order by id;"
qt_select_5 "select c_array1, c_array2, array_exists(x->x,c_array1) from ${tableName} order by id;"
qt_select_6 "select c_array1, c_array2, array_exists(x->x+2,c_array1) from ${tableName} order by id;"
qt_select_7 "select c_array1, c_array2, array_exists(x->power(x,2)>10,c_array1) from ${tableName} order by id;"
qt_select_8 "select array_exists(x -> x,[]);"
qt_select_9 "select array_exists(x -> x,[null]);"
qt_select_10 "select array_exists(x -> x,[1, 0]);"
qt_select_11 "select array_exists(x -> x is null, [null, 1, 2]);"
qt_select_12 "select *, array_exists([1,2,3]) from ${tableName} order by id;"
qt_select_13 "select c_array1, c_array2, array_exists(c_array1) from ${tableName} order by id;"
qt_select_14 "select array_exists([]);"
qt_select_15 "select array_exists([null, 1, 2]);"
sql "DROP TABLE IF EXISTS ${tableName}"
}