// Copyright 2023 PingCAP, Inc. // // Licensed 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 #include namespace DB { using Sizes = std::vector; /// Reference to the row in block. struct RowRef { const Block * block; UInt32 row_num; RowRef() = default; RowRef(const Block * block_, size_t row_num_) : block(block_) , row_num(row_num_) {} }; enum class CachedColumnState { NOT_CACHED, CONSTRUCT_CACHE, CACHED, }; struct CachedColumnInfo { std::mutex mu; Columns columns; CachedColumnState state = CachedColumnState::NOT_CACHED; void * next; explicit CachedColumnInfo(void * next_) : next(next_) {} }; /// Single linked list of references to rows. Used for ALL JOINs (non-unique JOINs) struct RowRefList : RowRef { UInt32 list_length = 0; union { RowRefList * next = nullptr; CachedColumnInfo * cached_column_info; }; RowRefList() = default; RowRefList(const Block * block_, size_t row_num_) : RowRef(block_, row_num_) {} /// for head node RowRefList(const Block * block_, size_t row_num_, bool sentinel_head) : RowRef(block_, row_num_) , list_length(sentinel_head ? 0 : 1) {} }; /// Single linked list of references to rows with used flag for each row struct RowRefListWithUsedFlag : RowRef { UInt32 list_length = 0; using Base_t = RowRefListWithUsedFlag; mutable std::atomic used{}; union { RowRefListWithUsedFlag * next = nullptr; CachedColumnInfo * cached_column_info; }; void setUsed() const { used.store(true, std::memory_order_relaxed); } /// Could be set simultaneously from different threads. bool getUsed() const { return used.load(std::memory_order_relaxed); } RowRefListWithUsedFlag() = default; RowRefListWithUsedFlag(const Block * block_, size_t row_num_) : RowRef(block_, row_num_) {} /// for head node RowRefListWithUsedFlag(const Block * block_, size_t row_num_, bool sentinel_head) : RowRef(block_, row_num_) , list_length(sentinel_head ? 0 : 1) {} }; /** Depending on template parameter, adds or doesn't add a flag, that element was used (row was joined). * For implementation of RIGHT and FULL JOINs. * NOTE: It is possible to store the flag in one bit of pointer to block or row_num. It seems not reasonable, because memory saving is minimal. */ template struct WithUsedFlag; template struct WithUsedFlag : Base { mutable std::atomic used{}; using Base::Base; using Base_t = Base; void setUsed() const { used.store(true, std::memory_order_relaxed); } /// Could be set simultaneously from different threads. bool getUsed() const { return used.load(std::memory_order_relaxed); } }; template struct WithUsedFlag : Base { using Base::Base; using Base_t = Base; void setUsed() const {} bool getUsed() const { return true; } }; /// Different types of keys for maps. #define APPLY_FOR_JOIN_VARIANTS(M) \ M(key8) \ M(key16) \ M(key32) \ M(key64) \ M(key_string) \ M(key_strbinpadding) \ M(key_strbin) \ M(key_fixed_string) \ M(keys128) \ M(keys256) \ M(serialized) enum class JoinMapMethod { EMPTY, CROSS, #define M(NAME) NAME, APPLY_FOR_JOIN_VARIANTS(M) #undef M }; /** Different data structures, that are used to perform JOIN. */ template struct ConcurrentMapsTemplate { using MappedType = Mapped; using key8Type = ConcurrentHashMap>; using key16Type = ConcurrentHashMap>; using key32Type = ConcurrentHashMap>; using key64Type = ConcurrentHashMap>; using key_stringType = ConcurrentHashMapWithSavedHash; using key_strbinpaddingType = ConcurrentHashMapWithSavedHash; using key_strbinType = ConcurrentHashMapWithSavedHash; using key_fixed_stringType = ConcurrentHashMapWithSavedHash; using keys128Type = ConcurrentHashMap>; using keys256Type = ConcurrentHashMap>; using serializedType = ConcurrentHashMapWithSavedHash; std::unique_ptr key8; std::unique_ptr key16; std::unique_ptr key32; std::unique_ptr key64; std::unique_ptr key_string; std::unique_ptr key_strbinpadding; std::unique_ptr key_strbin; std::unique_ptr key_fixed_string; std::unique_ptr keys128; std::unique_ptr keys256; std::unique_ptr serialized; // TODO: add more cases like Aggregator }; template struct MapsTemplate { using MappedType = typename Mapped::Base_t; using key8Type = HashMap>; using key16Type = HashMap>; using key32Type = HashMap>; using key64Type = HashMap>; using key_stringType = HashMapWithSavedHash; using key_strbinpaddingType = HashMapWithSavedHash; using key_strbinType = HashMapWithSavedHash; using key_fixed_stringType = HashMapWithSavedHash; using keys128Type = HashMap>; using keys256Type = HashMap>; using serializedType = HashMapWithSavedHash; std::unique_ptr key8; std::unique_ptr key16; std::unique_ptr key32; std::unique_ptr key64; std::unique_ptr key_string; std::unique_ptr key_strbinpadding; std::unique_ptr key_strbin; std::unique_ptr key_fixed_string; std::unique_ptr keys128; std::unique_ptr keys256; std::unique_ptr serialized; // TODO: add more cases like Aggregator }; struct MapsAny { using MappedType = VoidMapped; using key8Type = HashSet>; using key16Type = HashSet>; using key32Type = HashSet>; using key64Type = HashSet>; using key_stringType = HashSetWithSavedHash; using key_strbinpaddingType = HashSetWithSavedHash; using key_strbinType = HashSetWithSavedHash; using key_fixed_stringType = HashSetWithSavedHash; using keys128Type = HashSet>; using keys256Type = HashSet>; using serializedType = HashSetWithSavedHash; std::unique_ptr key8; std::unique_ptr key16; std::unique_ptr key32; std::unique_ptr key64; std::unique_ptr key_string; std::unique_ptr key_strbinpadding; std::unique_ptr key_strbin; std::unique_ptr key_fixed_string; std::unique_ptr keys128; std::unique_ptr keys256; std::unique_ptr serialized; // TODO: add more cases like Aggregator }; using ConcurrentMapsAll = ConcurrentMapsTemplate>; using ConcurrentMapsAllFull = ConcurrentMapsTemplate>; using ConcurrentMapsAllFullWithRowFlag = ConcurrentMapsTemplate; using MapsAll = MapsTemplate>; using MapsAllFull = MapsTemplate>; using MapsAllFullWithRowFlag = MapsTemplate; // With flag for every row ref JoinMapMethod chooseJoinMapMethod( const ColumnRawPtrs & key_columns, Sizes & key_sizes, const TiDB::TiDBCollators & collators); } // namespace DB