diff --git a/be/src/vec/functions/function.h b/be/src/vec/functions/function.h index a77812559b07ac..43ab3aaba920d9 100644 --- a/be/src/vec/functions/function.h +++ b/be/src/vec/functions/function.h @@ -388,6 +388,7 @@ class IFunction : public std::enable_shared_from_this, public: String get_name() const override = 0; + /// Notice: We should not change the column in the block, because the column may be shared by multiple expressions or exec nodes. virtual Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, size_t result, size_t input_rows_count) const override = 0; diff --git a/be/src/vec/functions/function_map.cpp b/be/src/vec/functions/function_map.cpp index 8e8f6b28cd81fd..3269dde41cbada 100644 --- a/be/src/vec/functions/function_map.cpp +++ b/be/src/vec/functions/function_map.cpp @@ -104,14 +104,16 @@ class FunctionMap : public IFunction { result_col_map_offsets.resize(input_rows_count); std::unique_ptr col_const = std::make_unique_for_overwrite(num_element); + std::vector arg(num_element); for (size_t i = 0; i < num_element; ++i) { auto& col = block.get_by_position(arguments[i]).column; std::tie(col, col_const[i]) = unpack_if_const(col); bool is_nullable = i % 2 == 0 ? result_col_map_keys_data.is_nullable() : result_col_map_vals_data.is_nullable(); // convert to nullable column + arg[i] = col; if (is_nullable && !col->is_nullable()) { - col = ColumnNullable::create(col, ColumnUInt8::create(col->size(), 0)); + arg[i] = ColumnNullable::create(col, ColumnUInt8::create(col->size(), 0)); } } @@ -119,11 +121,9 @@ class FunctionMap : public IFunction { ColumnArray::Offset64 offset = 0; for (size_t row = 0; row < input_rows_count; ++row) { for (size_t i = 0; i < num_element; i += 2) { - result_col_map_keys_data.insert_from(*block.get_by_position(arguments[i]).column, - index_check_const(row, col_const[i])); - result_col_map_vals_data.insert_from( - *block.get_by_position(arguments[i + 1]).column, - index_check_const(row, col_const[i + 1])); + result_col_map_keys_data.insert_from(*arg[i], index_check_const(row, col_const[i])); + result_col_map_vals_data.insert_from(*arg[i + 1], + index_check_const(row, col_const[i + 1])); } offset += num_element / 2; result_col_map_offsets[row] = offset; diff --git a/be/src/vec/functions/function_struct.cpp b/be/src/vec/functions/function_struct.cpp index c3a5eb6dc5672e..a106c14b835b68 100644 --- a/be/src/vec/functions/function_struct.cpp +++ b/be/src/vec/functions/function_struct.cpp @@ -93,21 +93,22 @@ class FunctionStruct : public IFunction { "function {} args number {} is not equal to result struct field number {}.", get_name(), num_element, struct_column->tuple_size()); } + std::vector arg(num_element); for (size_t i = 0; i < num_element; ++i) { auto& nested_col = struct_column->get_column(i); nested_col.reserve(input_rows_count); bool is_nullable = nested_col.is_nullable(); auto& col = block.get_by_position(args_num[i]).column; col = col->convert_to_full_column_if_const(); + arg[i] = col; if (is_nullable && !col->is_nullable()) { - col = ColumnNullable::create(col, ColumnUInt8::create(col->size(), 0)); + arg[i] = ColumnNullable::create(col, ColumnUInt8::create(col->size(), 0)); } } // insert value into struct column by column for (size_t i = 0; i < num_element; ++i) { - struct_column->get_column(i).insert_range_from( - *block.get_by_position(args_num[i]).column, 0, input_rows_count); + struct_column->get_column(i).insert_range_from(*arg[i], 0, input_rows_count); } block.replace_by_position(result, std::move(result_col)); return Status::OK(); diff --git a/regression-test/data/datatype_p0/nested_types/query/map_functions/test_map_with_agg.out b/regression-test/data/datatype_p0/nested_types/query/map_functions/test_map_with_agg.out new file mode 100644 index 00000000000000..c89a6f7e8a185b --- /dev/null +++ b/regression-test/data/datatype_p0/nested_types/query/map_functions/test_map_with_agg.out @@ -0,0 +1,9 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !old_sql -- +1 expr_seach {"exp_seac":8} +1 express_search {"exp_seac":6} + +-- !nereid_sql -- +1 expr_seach {"exp_seac":8} +1 express_search {"exp_seac":6} + diff --git a/regression-test/suites/datatype_p0/nested_types/query/map_functions/test_map_with_agg.groovy b/regression-test/suites/datatype_p0/nested_types/query/map_functions/test_map_with_agg.groovy new file mode 100644 index 00000000000000..eee045fd2ed48e --- /dev/null +++ b/regression-test/suites/datatype_p0/nested_types/query/map_functions/test_map_with_agg.groovy @@ -0,0 +1,55 @@ +// 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_map_with_agg", "p0") { + // create table + sql """ DROP TABLE IF EXISTS t_map_count;""" + sql """ CREATE TABLE IF NOT EXISTS t_map_count(id int(11), c_char VARCHAR(20), p1 varchar(200), p2 varchar(200), et VARCHAR(30), uid VARCHAR(100)) + ENGINE=OLAP DUPLICATE KEY(`id`, `c_char`, `p1`) DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES('replication_num' = '1');""" + + // insert data + sql """ INSERT INTO t_map_count VALUES(1, 'express_search','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'express_search','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'express_search','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'express_search','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'express_search','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'express_search','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + sql """ INSERT INTO t_map_count VALUES(1, 'expr_seach','consumer-un','17469174857s957ssf','page_l','36e44300d6c7433784852347b167ccdbd');""" + + sql """ set parallel_pipeline_task_num=5; """ + + // test in old planner + sql """set enable_nereids_planner=false""" + order_qt_old_sql """ SELECT id, c_char, map('exp_sea', 1) as m FROM t_map_count WHERE p1 = 'comr' AND p2 = 'ex' GROUP BY 1,2 + union all + SELECT id, c_char, map('exp_seac', count(CASE WHEN et = 'page_l' THEN uid END )) as m FROM t_map_count WHERE p1 = 'consumer-un' AND p2 = '17469174857s957ssf' GROUP BY 1,2;""" + + + // test in nereids planner + sql """set enable_nereids_planner=true""" + sql """ set enable_fallback_to_original_planner=false""" + order_qt_nereid_sql """ SELECT id, c_char, map('exp_sea', 1) as m FROM t_map_count WHERE p1 = 'comr' AND p2 = 'ex' GROUP BY 1,2 + union all + SELECT id, c_char, map('exp_seac', count(CASE WHEN et = 'page_l' THEN uid END )) as m FROM t_map_count WHERE p1 = 'consumer-un' AND p2 = '17469174857s957ssf' GROUP BY 1,2;""" +}