// 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 requires(sizeof...(Ts) > 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