diff --git a/be/src/vec/functions/array/function_array_intersect.cpp b/be/src/vec/functions/array/function_array_intersect.cpp index ed14195bca..cc27e1a665 100644 --- a/be/src/vec/functions/array/function_array_intersect.cpp +++ b/be/src/vec/functions/array/function_array_intersect.cpp @@ -17,11 +17,10 @@ #include "vec/columns/column_const.h" #include "vec/common/assert_cast.h" -#include "vec/common/string_ref.h" -#include "vec/data_types/data_type.h" -#include "vec/data_types/data_type_nullable.h" +#include "vec/common/hash_table/hash_map.h" #include "vec/functions/array/function_array_binary.h" -#include "vec/functions/array/function_array_set.h" +#include "vec/functions/array/function_array_map.h" +#include "vec/functions/array/function_array_nary.h" #include "vec/functions/simple_function_factory.h" namespace doris::vectorized { @@ -30,57 +29,52 @@ struct NameArrayIntersect { static constexpr auto name = "array_intersect"; }; -template +template struct IntersectAction { - // True if set has null element - bool null_flag = false; + // True if current has null element + bool current_null_flag = false; // True if result_set has null element - bool result_null_flag = false; + bool result_null_flag = true; // True if it should execute the left array first. - static constexpr auto execute_left_column_first = false; + typename Map::mapped_type* value = nullptr; // Handle Null element. - // Return true means this null element should put into result column. - template - bool apply_null() { - if constexpr (is_left) { - if (!result_null_flag) { - result_null_flag = true; - return null_flag; - } - } else { - if (!null_flag) { - null_flag = true; - } - } - return false; - } + bool apply_null() { return result_null_flag; } // Handle Non-Null element. - // Return ture means this Non-Null element should put into result column. - template - bool apply(Set& set, Set& result_set, const Element& elem) { - if constexpr (is_left) { - if (set.find(elem) && !result_set.find(elem)) { - result_set.insert(elem); - return true; - } - } else { - if (!set.find(elem)) { - set.insert(elem); + void apply(Map& map, const int arg_idx, const int row_idx, + const ColumnArrayExecutionData& param) { + current_null_flag = false; + size_t start_off = (*param.offsets_ptr)[row_idx - 1]; + size_t end_off = (*param.offsets_ptr)[row_idx]; + for (size_t off = start_off; off < end_off; ++off) { + if (param.nested_nullmap_data && param.nested_nullmap_data[off]) { + current_null_flag = true; + } else { + if constexpr (std::is_same_v) { + value = &map[param.nested_col->get_data_at(off)]; + } else { + auto& data_col = static_cast(*param.nested_col); + value = &map[data_col.get_element(off)]; + } + if (*value == arg_idx) { + ++(*value); + } } } - return false; + if (!current_null_flag) { + result_null_flag = false; + } } void reset() { - null_flag = false; - result_null_flag = false; + current_null_flag = false; + result_null_flag = true; } }; using FunctionArrayIntersect = - FunctionArrayBinary, NameArrayIntersect>; + FunctionArrayNary, NameArrayIntersect>; void register_function_array_intersect(SimpleFunctionFactory& factory) { factory.register_function(); diff --git a/be/src/vec/functions/array/function_array_map.h b/be/src/vec/functions/array/function_array_map.h new file mode 100644 index 0000000000..ccf5603942 --- /dev/null +++ b/be/src/vec/functions/array/function_array_map.h @@ -0,0 +1,193 @@ +// 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. + +#pragma once + +#include + +#include "vec/columns/column_array.h" +#include "vec/columns/column_string.h" +#include "vec/common/hash_table/hash_map.h" +#include "vec/common/hash_table/hash_set.h" +#include "vec/data_types/data_type_array.h" +#include "vec/functions/array/function_array_utils.h" +#include "vec/functions/function_helpers.h" + +namespace doris::vectorized { + +enum class MapOperation { INTERSECT }; + +template +struct IntersectAction; + +template +struct MapActionImpl; + +template +struct MapActionImpl { + using Action = IntersectAction; +}; + +template +struct OpenMapImpl { + using Element = typename ColumnType::value_type; + using ElementNativeType = typename NativeType::Type; + using Map = + HashMapWithStackMemory, 6>; + using Action = typename MapActionImpl::Action; + + Action action; + Map map; + void reset() { + map.clear(); + action.reset(); + } + + // this method calculate rows to get a rest dst data + void apply(ColumnArrayMutableData& dst, const ColumnArrayExecutionDatas params, + std::vector& col_const, int start_row, int end_row) { + size_t dst_off = 0; + for (int row = start_row; row < end_row; ++row) { + map.clear(); + for (int i = 0; i < params.size(); ++i) { + action.apply(map, i, index_check_const(row, col_const[i]), params[i]); + } + // nullmap + if (action.apply_null()) { + ++dst_off; + dst.nested_col->insert_default(); + if (dst.nested_nullmap_data) { + dst.nested_nullmap_data->push_back(1); + } + } + // make map result to dst + for (const auto& entry : map) { + if (entry.get_mapped() == params.size()) { + ++dst_off; + auto& dst_data = static_cast(*dst.nested_col).get_data(); + dst_data.push_back(entry.get_first()); + if (dst.nested_nullmap_data) { + dst.nested_nullmap_data->push_back(0); + } + } + } + dst.offsets_ptr->push_back(dst_off); + } + } +}; + +template +struct OpenMapImpl { + using Map = HashMapWithStackMemory; + using Action = typename MapActionImpl::Action; + + Action action; + Map map; + + void reset() { + map.clear(); + action.reset(); + } + + void apply(ColumnArrayMutableData& dst, const ColumnArrayExecutionDatas params, + std::vector& col_const, int start_row, int end_row) { + size_t dst_off = 0; + for (int row = start_row; row < end_row; ++row) { + map.clear(); + for (int i = 0; i < params.size(); ++i) { + action.apply(map, i, index_check_const(row, col_const[i]), params[i]); + } + // nullmap + if (action.apply_null()) { + ++dst_off; + dst.nested_col->insert_default(); + if (dst.nested_nullmap_data) { + dst.nested_nullmap_data->push_back(1); + } + } + // make map result to dst + for (const auto& entry : map) { + if (entry.get_mapped() == params.size()) { + auto& dst_col = static_cast(*dst.nested_col); + StringRef key = entry.get_first(); + ++dst_off; + dst_col.insert_data(key.data, key.size); + if (dst.nested_nullmap_data) { + dst.nested_nullmap_data->push_back(0); + } + } + } + dst.offsets_ptr->push_back(dst_off); + } + } +}; + +template +struct ArrayMapImpl { +public: + static DataTypePtr get_return_type(const DataTypes& arguments) { + DataTypePtr res; + // if any nested type of array arguments is nullable then return array with + // nullable nested type. + for (const auto& arg : arguments) { + const DataTypeArray* array_type = check_and_get_data_type(arg.get()); + if (array_type->get_nested_type()->is_nullable()) { + res = arg; + break; + } + } + res = res ? res : arguments[0]; + return res; + } + + static Status execute(ColumnPtr& res_ptr, ColumnArrayExecutionDatas datas, + std::vector& col_const, int start_row, int end_row) { + ColumnArrayMutableData dst = + create_mutable_data(datas[0].nested_col, datas[0].nested_nullmap_data); + if (_execute_internal(dst, datas, col_const, start_row, end_row)) { + res_ptr = assemble_column_array(dst); + return Status::OK(); + } + return Status::RuntimeError("Unexpected columns"); + } + +private: + template + static bool _execute_internal(ColumnArrayMutableData& dst, ColumnArrayExecutionDatas datas, + std::vector& col_const, int start_row, int end_row) { + for (auto data : datas) { + if (!check_column(*data.nested_col)) { + return false; + } + } + // do check staff + using Impl = OpenMapImpl; + Impl impl; + ColumnPtr res_column; + impl.apply(dst, datas, col_const, start_row, end_row); + return true; + } + + template 0), int> = 0> + static bool _execute_internal(ColumnArrayMutableData& dst, ColumnArrayExecutionDatas datas, + std::vector& col_const, int start_row, int end_row) { + return _execute_internal(dst, datas, col_const, start_row, end_row) || + _execute_internal(dst, datas, col_const, start_row, end_row); + } +}; + +} // namespace doris::vectorized \ No newline at end of file diff --git a/be/src/vec/functions/array/function_array_nary.h b/be/src/vec/functions/array/function_array_nary.h new file mode 100644 index 0000000000..bc42585439 --- /dev/null +++ b/be/src/vec/functions/array/function_array_nary.h @@ -0,0 +1,82 @@ +// 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. + +#pragma once + +#include "vec/columns/column_array.h" +#include "vec/data_types/data_type_array.h" +#include "vec/data_types/data_type_number.h" +#include "vec/functions/array/function_array_utils.h" +#include "vec/functions/function.h" +#include "vec/functions/function_helpers.h" + +namespace doris::vectorized { + +// Functions with more than two arrays of the same element type. +template +class FunctionArrayNary : public IFunction { +public: + static constexpr auto name = Name::name; + static FunctionPtr create() { return std::make_shared(); } + String get_name() const override { return name; } + bool is_variadic() const override { return true; } + size_t get_number_of_arguments() const override { return 0; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + DCHECK(arguments.size() >= 2) + << "function: " << get_name() << ", arguments should large equals than 2"; + CHECK(is_array(remove_nullable(arguments[0]))) + << "0-th element is " << arguments[0]->get_name() << ",not array type"; + auto nested_type = remove_nullable( + assert_cast(*(arguments[0])).get_nested_type()); + for (size_t i = 1; i < arguments.size(); ++i) { + CHECK(is_array(remove_nullable(arguments[i]))) + << i << "-th element is " << arguments[i]->get_name() << ", not array type"; + auto right_nested_type = remove_nullable( + assert_cast(*(remove_nullable(arguments[i]))) + .get_nested_type()); + // do check array nested data type, now we just support same nested data type + CHECK(nested_type->equals(*right_nested_type)) + << "data type " << arguments[i]->get_name() << " not equal with " + << arguments[0]->get_name(); + } + DataTypePtr res_data_type = Impl::get_return_type(arguments); + return res_data_type; + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) override { + ColumnPtr res_ptr; + ColumnArrayExecutionDatas datas(arguments.size()); + std::vector col_const(arguments.size()); + for (int i = 0; i < arguments.size(); ++i) { + const auto& [col, is_const] = + unpack_if_const(block.get_by_position(arguments[i]).column); + col_const[i] = is_const; + extract_column_array_info(*col, datas[i]); + } + if (Status st = Impl::execute(res_ptr, datas, col_const, 0, input_rows_count); + st != Status::OK()) { + return Status::RuntimeError( + fmt::format("function {} execute failed {} ", get_name(), st.to_string())); + } + block.replace_by_position(result, std::move(res_ptr)); + return Status::OK(); + } +}; + +} // namespace doris::vectorized diff --git a/be/src/vec/functions/array/function_array_set.h b/be/src/vec/functions/array/function_array_set.h index f81c04b7d2..d8e0a156ba 100644 --- a/be/src/vec/functions/array/function_array_set.h +++ b/be/src/vec/functions/array/function_array_set.h @@ -28,7 +28,7 @@ namespace doris::vectorized { -enum class SetOperation { UNION, EXCEPT, INTERSECT }; +enum class SetOperation { UNION, EXCEPT }; template struct UnionAction; @@ -36,9 +36,6 @@ struct UnionAction; template struct ExceptAction; -template -struct IntersectAction; - template struct ActionImpl; @@ -52,11 +49,6 @@ struct ActionImpl { using Action = ExceptAction; }; -template -struct ActionImpl { - using Action = IntersectAction; -}; - template struct OpenSetImpl { using Element = typename ColumnType::value_type; diff --git a/be/src/vec/functions/array/function_array_union.cpp b/be/src/vec/functions/array/function_array_union.cpp index 641063103c..68c9c2043f 100644 --- a/be/src/vec/functions/array/function_array_union.cpp +++ b/be/src/vec/functions/array/function_array_union.cpp @@ -21,6 +21,7 @@ #include "vec/data_types/data_type.h" #include "vec/data_types/data_type_nullable.h" #include "vec/functions/array/function_array_binary.h" +#include "vec/functions/array/function_array_nary.h" #include "vec/functions/array/function_array_set.h" #include "vec/functions/simple_function_factory.h" diff --git a/be/src/vec/functions/array/function_array_utils.h b/be/src/vec/functions/array/function_array_utils.h index a9b303934c..36bf811b77 100644 --- a/be/src/vec/functions/array/function_array_utils.h +++ b/be/src/vec/functions/array/function_array_utils.h @@ -17,6 +17,7 @@ #pragma once #include "vec/columns/column_array.h" +#include "vec/columns/column_nullable.h" #include "vec/columns/columns_number.h" #include "vec/core/types.h" #include "vec/data_types/data_type.h" @@ -29,6 +30,15 @@ class IColumn; namespace doris::vectorized { +struct ColumnArrayMutableData { +public: + MutableColumnPtr array_nested_col = nullptr; + ColumnUInt8::Container* nested_nullmap_data = nullptr; + MutableColumnPtr offsets_col = nullptr; + ColumnArray::Offsets64* offsets_ptr = nullptr; + IColumn* nested_col = nullptr; +}; + struct ColumnArrayExecutionData { public: void reset() { @@ -45,17 +55,34 @@ public: const ColumnArray::Offsets64* offsets_ptr = nullptr; const UInt8* nested_nullmap_data = nullptr; const IColumn* nested_col = nullptr; -}; -struct ColumnArrayMutableData { -public: - MutableColumnPtr array_nested_col = nullptr; - ColumnUInt8::Container* nested_nullmap_data = nullptr; - MutableColumnPtr offsets_col = nullptr; - ColumnArray::Offsets64* offsets_ptr = nullptr; - IColumn* nested_col = nullptr; + ColumnArrayMutableData to_mutable_data() const { + ColumnArrayMutableData dst; + dst.offsets_col = ColumnArray::ColumnOffsets::create(); + dst.offsets_ptr = + &reinterpret_cast(dst.offsets_col.get())->get_data(); + dst.array_nested_col = + ColumnNullable::create(nested_col->clone_empty(), ColumnUInt8::create()); + auto* nullable_col = reinterpret_cast(dst.array_nested_col.get()); + dst.nested_nullmap_data = &nullable_col->get_null_map_data(); + dst.nested_col = nullable_col->get_nested_column_ptr().get(); + for (size_t row = 0; row < offsets_ptr->size(); ++row) { + dst.offsets_ptr->push_back((*offsets_ptr)[row]); + size_t off = (*offsets_ptr)[row - 1]; + size_t len = (*offsets_ptr)[row] - off; + for (int start = off; start < off + len; ++start) { + if (nested_nullmap_data && nested_nullmap_data[start]) { + dst.nested_col->insert_default(); + dst.nested_nullmap_data->push_back(1); + } else { + dst.nested_col->insert_from(*nested_col, start); + dst.nested_nullmap_data->push_back(0); + } + } + } + return dst; + } }; - bool extract_column_array_info(const IColumn& src, ColumnArrayExecutionData& data); ColumnArrayMutableData create_mutable_data(const IColumn* nested_col, bool is_nullable); @@ -66,4 +93,5 @@ MutableColumnPtr assemble_column_array(ColumnArrayMutableData& data); void slice_array(ColumnArrayMutableData& dst, ColumnArrayExecutionData& src, const IColumn& offset_column, const IColumn* length_column); +using ColumnArrayExecutionDatas = std::vector; } // namespace doris::vectorized diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java index 22d0bcd65c..9785988f31 100644 --- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java +++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java @@ -710,8 +710,8 @@ public abstract class Type { } else if (sourceType.isMapType() && targetType.isMapType()) { return MapType.canCastTo((MapType) sourceType, (MapType) targetType); } else if (targetType.isArrayType() && !((ArrayType) targetType).getItemType().isScalarType() - && !sourceType.isNull()) { - // TODO: current not support cast any non-array type(except for null) to nested array type. + && !sourceType.isNull() && !sourceType.isStringType()) { + // TODO: current not support cast any non-array type(except null and charFamily) to nested array type. return false; } else if ((targetType.isStructType() || targetType.isMapType()) && sourceType.isStringType()) { return true; diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 611569520e..464d665390 100644 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -544,24 +544,24 @@ visible_functions = { [['array_compact'], 'ARRAY_DECIMAL128', ['ARRAY_DECIMAL128'], ''], [['array_compact'], 'ARRAY_VARCHAR', ['ARRAY_VARCHAR'], ''], - [['array_intersect'], 'ARRAY_BOOLEAN', ['ARRAY_BOOLEAN', 'ARRAY_BOOLEAN'], ''], - [['array_intersect'], 'ARRAY_TINYINT', ['ARRAY_TINYINT', 'ARRAY_TINYINT'], ''], - [['array_intersect'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT'], ''], - [['array_intersect'], 'ARRAY_INT', ['ARRAY_INT', 'ARRAY_INT'], ''], - [['array_intersect'], 'ARRAY_BIGINT', ['ARRAY_BIGINT', 'ARRAY_BIGINT'], ''], - [['array_intersect'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT'], ''], - [['array_intersect'], 'ARRAY_FLOAT', ['ARRAY_FLOAT', 'ARRAY_FLOAT'], ''], - [['array_intersect'], 'ARRAY_DOUBLE', ['ARRAY_DOUBLE', 'ARRAY_DOUBLE'], ''], - [['array_intersect'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2'], ''], - [['array_intersect'], 'ARRAY_DECIMAL32', ['ARRAY_DECIMAL32', 'ARRAY_DECIMAL32'], ''], - [['array_intersect'], 'ARRAY_DECIMAL64', ['ARRAY_DECIMAL64', 'ARRAY_DECIMAL64'], ''], - [['array_intersect'], 'ARRAY_DECIMAL128', ['ARRAY_DECIMAL128', 'ARRAY_DECIMAL128'], ''], - [['array_intersect'], 'ARRAY_DATETIME', ['ARRAY_DATETIME', 'ARRAY_DATETIME'], ''], - [['array_intersect'], 'ARRAY_DATE', ['ARRAY_DATE', 'ARRAY_DATE'], ''], - [['array_intersect'], 'ARRAY_DATETIMEV2', ['ARRAY_DATETIMEV2', 'ARRAY_DATETIMEV2'], ''], - [['array_intersect'], 'ARRAY_DATEV2', ['ARRAY_DATEV2', 'ARRAY_DATEV2'], ''], - [['array_intersect'], 'ARRAY_VARCHAR', ['ARRAY_VARCHAR', 'ARRAY_VARCHAR'], ''], - [['array_intersect'], 'ARRAY_STRING', ['ARRAY_STRING', 'ARRAY_STRING'], ''], + [['array_intersect'], 'ARRAY_BOOLEAN', ['ARRAY_BOOLEAN', 'ARRAY_BOOLEAN', '...'], ''], + [['array_intersect'], 'ARRAY_TINYINT', ['ARRAY_TINYINT', 'ARRAY_TINYINT', '...'], ''], + [['array_intersect'], 'ARRAY_SMALLINT', ['ARRAY_SMALLINT', 'ARRAY_SMALLINT', '...'], ''], + [['array_intersect'], 'ARRAY_INT', ['ARRAY_INT', 'ARRAY_INT', '...'], ''], + [['array_intersect'], 'ARRAY_BIGINT', ['ARRAY_BIGINT', 'ARRAY_BIGINT', '...'], ''], + [['array_intersect'], 'ARRAY_LARGEINT', ['ARRAY_LARGEINT', 'ARRAY_LARGEINT', '...'], ''], + [['array_intersect'], 'ARRAY_FLOAT', ['ARRAY_FLOAT', 'ARRAY_FLOAT', '...'], ''], + [['array_intersect'], 'ARRAY_DOUBLE', ['ARRAY_DOUBLE', 'ARRAY_DOUBLE', '...'], ''], + [['array_intersect'], 'ARRAY_DECIMALV2', ['ARRAY_DECIMALV2', 'ARRAY_DECIMALV2', '...'], ''], + [['array_intersect'], 'ARRAY_DECIMAL32', ['ARRAY_DECIMAL32', 'ARRAY_DECIMAL32', '...'], ''], + [['array_intersect'], 'ARRAY_DECIMAL64', ['ARRAY_DECIMAL64', 'ARRAY_DECIMAL64', '...'], ''], + [['array_intersect'], 'ARRAY_DECIMAL128', ['ARRAY_DECIMAL128', 'ARRAY_DECIMAL128', '...'], ''], + [['array_intersect'], 'ARRAY_DATETIME', ['ARRAY_DATETIME', 'ARRAY_DATETIME', '...'], ''], + [['array_intersect'], 'ARRAY_DATE', ['ARRAY_DATE', 'ARRAY_DATE', '...'], ''], + [['array_intersect'], 'ARRAY_DATETIMEV2', ['ARRAY_DATETIMEV2', 'ARRAY_DATETIMEV2', '...'], ''], + [['array_intersect'], 'ARRAY_DATEV2', ['ARRAY_DATEV2', 'ARRAY_DATEV2', '...'], ''], + [['array_intersect'], 'ARRAY_VARCHAR', ['ARRAY_VARCHAR', 'ARRAY_VARCHAR', '...'], ''], + [['array_intersect'], 'ARRAY_STRING', ['ARRAY_STRING', 'ARRAY_STRING', '...'], ''], [['array_slice', '%element_slice%'], 'ARRAY_BOOLEAN', ['ARRAY_BOOLEAN', 'BIGINT'], ''], [['array_slice', '%element_slice%'], 'ARRAY_TINYINT', ['ARRAY_TINYINT', 'BIGINT'], ''], diff --git a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out index f3c72dc7aa..fc2b267878 100644 --- a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out +++ b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions.out @@ -297,15 +297,15 @@ 9 \N -- !select -- -1 [1, 2] +1 [2, 1] 2 [] 3 \N 4 [] 5 \N 6 \N 7 \N -8 [1, 2, 3] -9 [1, 2] +8 [3, 2, 1] +9 [2, 1] -- !select -- 1 [2023-02-06] diff --git a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out index 6adaea2c39..804e8472d1 100644 --- a/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out +++ b/regression-test/data/query_p0/sql_functions/array_functions/test_array_functions_by_literal.out @@ -414,7 +414,7 @@ true [1] -- !sql -- -[2, 3] +[3, 2] -- !sql -- [1, 2, 3, 4, NULL] @@ -423,7 +423,7 @@ true [1] -- !sql -- -[2, 3] +[3, 2] -- !sql -- [1, 0] @@ -533,6 +533,18 @@ true -- !sql -- [111.111, 222.222] +-- !sql_intersect_1 -- +[] + +-- !sql_intersect_2 -- +[NULL, 1] + +-- !sql_intersect_3 -- +[NULL, 1] + +-- !sql_intersect_4 -- +[] + -- !sql -- [2, 3, 4, 5, 6] diff --git a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy index 35ca5f3cd9..584750d1ca 100644 --- a/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy +++ b/regression-test/suites/query_p0/sql_functions/array_functions/test_array_functions_by_literal.groovy @@ -219,6 +219,12 @@ suite("test_array_functions_by_literal") { qt_sql "select (array(cast ('2023-02-06' as datev2), cast ('2023-02-05' as datev2)))[1:2]" qt_sql "select (array(cast (111.111 as decimalv3(6,3)),cast (222.222 as decimalv3(6,3))))[1:2]" + // array_intersect + qt_sql_intersect_1 "select array_intersect([1,2,3], [1,2,3], [null])" + qt_sql_intersect_2 "select array_intersect([1, 2, null], [1, 3, null], [1,2,3,null])" + qt_sql_intersect_3 "select array_intersect([1,2,3, null], [1,2,3,null], [1,2,null], [1, null])" + qt_sql_intersect_4 "select array_intersect([1,2,3], [1,2,3], [null], [])" + // array_popfront function qt_sql "select array_popfront([1,2,3,4,5,6])" qt_sql "select array_popfront([])"