From 8ea4d7987be4ed700d667571854e6d2460680c9f Mon Sep 17 00:00:00 2001 From: Amos Bird Date: Sun, 30 Dec 2018 23:54:45 +0800 Subject: [PATCH 1/4] Add join_overwrite settings for StorageJoin. This makes using StorageJoin as dictionary more flexible. --- dbms/src/Interpreters/Join.cpp | 121 ++++++---------- dbms/src/Interpreters/Join.h | 131 +++++++++++++++--- dbms/src/Interpreters/Settings.h | 1 + dbms/src/Storages/StorageJoin.cpp | 19 ++- dbms/src/Storages/StorageJoin.h | 3 +- .../00830_join_overwrite.reference | 2 + .../0_stateless/00830_join_overwrite.sql | 15 ++ libs/libcommon/CMakeLists.txt | 1 + .../include/common/constexpr_helpers.h | 31 +++++ 9 files changed, 219 insertions(+), 105 deletions(-) create mode 100644 dbms/tests/queries/0_stateless/00830_join_overwrite.reference create mode 100644 dbms/tests/queries/0_stateless/00830_join_overwrite.sql create mode 100644 libs/libcommon/include/common/constexpr_helpers.h diff --git a/dbms/src/Interpreters/Join.cpp b/dbms/src/Interpreters/Join.cpp index 8783d16c3c1..da8209a09d3 100644 --- a/dbms/src/Interpreters/Join.cpp +++ b/dbms/src/Interpreters/Join.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -32,10 +34,11 @@ namespace ErrorCodes Join::Join(const Names & key_names_right_, bool use_nulls_, const SizeLimits & limits, - ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_) + ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_, bool overwrite_) : kind(kind_), strictness(strictness_), key_names_right(key_names_right_), use_nulls(use_nulls_), + overwrite(overwrite_), log(&Logger::get("Join")), limits(limits) { @@ -177,21 +180,8 @@ void Join::init(Type type_) if (kind == ASTTableJoin::Kind::Cross) return; - - if (!getFullness(kind)) - { - if (strictness == ASTTableJoin::Strictness::Any) - initImpl(maps_any, type); - else - initImpl(maps_all, type); - } - else - { - if (strictness == ASTTableJoin::Strictness::Any) - initImpl(maps_any_full, type); - else - initImpl(maps_all_full, type); - } + dispatch(MapInitTag()); + dispatch([&](auto, auto, auto & map) { initImpl(map, type); }); } size_t Join::getTotalRowCount() const @@ -205,10 +195,7 @@ size_t Join::getTotalRowCount() const } else { - res += getTotalRowCountImpl(maps_any, type); - res += getTotalRowCountImpl(maps_all, type); - res += getTotalRowCountImpl(maps_any_full, type); - res += getTotalRowCountImpl(maps_all_full, type); + dispatch([&](auto, auto, auto & map) { res += getTotalRowCountImpl(map, type); }); } return res; @@ -225,10 +212,7 @@ size_t Join::getTotalByteCount() const } else { - res += getTotalByteCountImpl(maps_any, type); - res += getTotalByteCountImpl(maps_all, type); - res += getTotalByteCountImpl(maps_any_full, type); - res += getTotalByteCountImpl(maps_all_full, type); + dispatch([&](auto, auto, auto & map) { res += getTotalByteCountImpl(map, type); }); res += pool.size(); } @@ -326,6 +310,8 @@ namespace KeyGetter::onNewKey(it->first, pool); new (&it->second) typename Map::mapped_type(stored_block, i); } + else if (it->second.overwrite) + new (&it->second) typename Map::mapped_type(stored_block, i); } }; @@ -482,21 +468,9 @@ bool Join::insertFromBlock(const Block & block) if (kind != ASTTableJoin::Kind::Cross) { - /// Fill the hash table. - if (!getFullness(kind)) - { - if (strictness == ASTTableJoin::Strictness::Any) - insertFromBlockImpl(type, maps_any, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); - else - insertFromBlockImpl(type, maps_all, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); - } - else - { - if (strictness == ASTTableJoin::Strictness::Any) - insertFromBlockImpl(type, maps_any_full, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); - else - insertFromBlockImpl(type, maps_all_full, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); - } + dispatch([&](auto, auto strictness_, auto & map) { + insertFromBlockImpl(type, map, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); + }); } return limits.check(getTotalRowCount(), getTotalByteCount(), "JOIN", ErrorCodes::SET_SIZE_LIMIT_EXCEEDED); @@ -505,11 +479,11 @@ bool Join::insertFromBlock(const Block & block) namespace { - template + template struct Adder; template - struct Adder + struct Adder { static void addFound(const typename Map::const_iterator & it, size_t num_columns_to_add, MutableColumns & added_columns, size_t i, IColumn::Filter * filter, IColumn::Offset & /*current_offset*/, IColumn::Offsets * /*offsets*/, @@ -532,7 +506,7 @@ namespace }; template - struct Adder + struct Adder { static void addFound(const typename Map::const_iterator & it, size_t num_columns_to_add, MutableColumns & added_columns, size_t i, IColumn::Filter * filter, IColumn::Offset & /*current_offset*/, IColumn::Offsets * /*offsets*/, @@ -551,8 +525,8 @@ namespace } }; - template - struct Adder + template + struct Adder { static void addFound(const typename Map::const_iterator & it, size_t num_columns_to_add, MutableColumns & added_columns, size_t i, IColumn::Filter * filter, IColumn::Offset & current_offset, IColumn::Offsets * offsets, @@ -578,7 +552,7 @@ namespace { (*filter)[i] = 0; - if (KIND == ASTTableJoin::Kind::Inner) + if (!pad_left) { (*offsets)[i] = current_offset; } @@ -609,7 +583,7 @@ namespace { if (has_null_map && (*null_map)[i]) { - Adder::addNotFound( + Adder::pad_left, STRICTNESS, Map>::addNotFound( num_columns_to_add, added_columns, i, filter.get(), current_offset, offsets_to_replicate.get()); } else @@ -620,11 +594,11 @@ namespace if (it != map.end()) { it->second.setUsed(); - Adder::addFound( + Adder::pad_left, STRICTNESS, Map>::addFound( it, num_columns_to_add, added_columns, i, filter.get(), current_offset, offsets_to_replicate.get(), right_indexes); } else - Adder::addNotFound( + Adder::pad_left, STRICTNESS, Map>::addNotFound( num_columns_to_add, added_columns, i, filter.get(), current_offset, offsets_to_replicate.get()); } } @@ -655,7 +629,7 @@ void Join::joinBlockImpl( const Names & key_names_left, const NameSet & needed_key_names_right, const Block & block_with_columns_to_add, - const Maps & maps) const + const Maps & maps_) const { size_t keys_size = key_names_left.size(); ColumnRawPtrs key_columns(keys_size); @@ -749,7 +723,7 @@ void Join::joinBlockImpl( #define M(TYPE) \ case Join::Type::TYPE: \ joinBlockImplType::Type>(\ - *maps.TYPE, rows, key_columns, key_sizes, added_columns, null_map, \ + *maps_.TYPE, rows, key_columns, key_sizes, added_columns, null_map, \ filter, current_offset, offsets_to_replicate, right_indexes); \ break; APPLY_FOR_JOIN_VARIANTS(M) @@ -906,10 +880,10 @@ DataTypePtr Join::joinGetReturnType(const String & column_name) const template -void Join::joinGetImpl(Block & block, const String & column_name, const Maps & maps) const +void Join::joinGetImpl(Block & block, const String & column_name, const Maps & maps_) const { joinBlockImpl( - block, {block.getByPosition(0).name}, {}, {sample_block_with_columns_to_add.getByName(column_name)}, maps); + block, {block.getByPosition(0).name}, {}, {sample_block_with_columns_to_add.getByName(column_name)}, maps_); } @@ -926,7 +900,12 @@ void Join::joinGet(Block & block, const String & column_name) const checkTypeOfKey(block, sample_block_with_keys); if (kind == ASTTableJoin::Kind::Left && strictness == ASTTableJoin::Strictness::Any) - joinGetImpl(block, column_name, maps_any); + { + if (overwrite) + joinGetImpl(block, column_name, std::get(maps)); + else + joinGetImpl(block, column_name, std::get(maps)); + } else throw Exception("joinGet only supports StorageJoin of type Left Any", ErrorCodes::LOGICAL_ERROR); } @@ -940,30 +919,10 @@ void Join::joinBlock(Block & block, const Names & key_names_left, const NameSet checkTypesOfKeys(block, key_names_left, sample_block_with_keys); - if (kind == ASTTableJoin::Kind::Left && strictness == ASTTableJoin::Strictness::Any) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_any); - else if (kind == ASTTableJoin::Kind::Inner && strictness == ASTTableJoin::Strictness::Any) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_any); - else if (kind == ASTTableJoin::Kind::Left && strictness == ASTTableJoin::Strictness::All) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_all); - else if (kind == ASTTableJoin::Kind::Inner && strictness == ASTTableJoin::Strictness::All) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_all); - else if (kind == ASTTableJoin::Kind::Full && strictness == ASTTableJoin::Strictness::Any) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_any_full); - else if (kind == ASTTableJoin::Kind::Right && strictness == ASTTableJoin::Strictness::Any) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_any_full); - else if (kind == ASTTableJoin::Kind::Full && strictness == ASTTableJoin::Strictness::All) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_all_full); - else if (kind == ASTTableJoin::Kind::Right && strictness == ASTTableJoin::Strictness::All) - joinBlockImpl( - block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, maps_all_full); + if (dispatch([&](auto kind_, auto strictness_, auto & map) { + joinBlockImpl(block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, map); + })) + ; else if (kind == ASTTableJoin::Kind::Cross) joinBlockImplCross(block); else @@ -1112,12 +1071,12 @@ protected: if (parent.blocks.empty()) return Block(); - if (parent.strictness == ASTTableJoin::Strictness::Any) - return createBlock(parent.maps_any_full); - else if (parent.strictness == ASTTableJoin::Strictness::All) - return createBlock(parent.maps_all_full); + Block block; + if (parent.dispatch([&](auto, auto strictness, auto & map) { block = createBlock(map); })) + ; else throw Exception("Logical error: unknown JOIN strictness (must be ANY or ALL)", ErrorCodes::LOGICAL_ERROR); + return block; } private: diff --git a/dbms/src/Interpreters/Join.h b/dbms/src/Interpreters/Join.h index 65371239851..c1f665262a8 100644 --- a/dbms/src/Interpreters/Join.h +++ b/dbms/src/Interpreters/Join.h @@ -15,6 +15,8 @@ #include #include +#include +#include namespace DB @@ -221,7 +223,7 @@ class Join { public: Join(const Names & key_names_right_, bool use_nulls_, const SizeLimits & limits, - ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_); + ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_, bool overwrite_ = false); bool empty() { return type == Type::EMPTY; } @@ -289,15 +291,18 @@ public: /** 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. + * Depending on template parameter, decide whether to overwrite existing values when encountering the same key again + * with_used is for implementation of RIGHT and FULL JOINs. + * overwrite is for implementation of StorageJoin with overwrite setting enabled * 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 WithFlags; - template - struct WithUsedFlag : Base + template + struct WithFlags : Base { + static constexpr bool overwrite = overwrite_; mutable std::atomic used {}; using Base::Base; using Base_t = Base; @@ -305,9 +310,10 @@ public: bool getUsed() const { return used; } }; - template - struct WithUsedFlag : Base + template + struct WithFlags : Base { + static constexpr bool overwrite = overwrite_; using Base::Base; using Base_t = Base; void setUsed() const {} @@ -363,10 +369,80 @@ public: std::unique_ptr> hashed; }; - using MapsAny = MapsTemplate>; - using MapsAll = MapsTemplate>; - using MapsAnyFull = MapsTemplate>; - using MapsAllFull = MapsTemplate>; + using MapsAny = MapsTemplate>; + using MapsAnyOverwrite = MapsTemplate>; + using MapsAll = MapsTemplate>; + using MapsAnyFull = MapsTemplate>; + using MapsAnyFullOverwrite = MapsTemplate>; + using MapsAllFull = MapsTemplate>; + + template + struct KindTrait + { + // Affects the Adder trait so that when the right part is empty, adding a default value on the left + static constexpr bool pad_left = static_in_v; + + // Affects the Map trait so that a `used` flag is attached to map slots in order to + // generate default values on the right when the left part is empty + static constexpr bool pad_right = static_in_v; + }; + + template + struct MapGetterImpl; + + template + using Map = typename MapGetterImpl::pad_right, strictness, overwrite>::Map; + + static constexpr std::array STRICTNESSES = {ASTTableJoin::Strictness::Any, ASTTableJoin::Strictness::All}; + static constexpr std::array KINDS + = {ASTTableJoin::Kind::Left, ASTTableJoin::Kind::Inner, ASTTableJoin::Kind::Full, ASTTableJoin::Kind::Right}; + + struct MapInitTag {}; + + template + bool dispatch(Func && func) + { + if (overwrite) + return static_for<0, KINDS.size()>([&](auto i) { + if (kind == KINDS[i] && strictness == ASTTableJoin::Strictness::Any) + { + if constexpr (std::is_same_v) + maps = Map(); + else + func( + std::integral_constant(), + std::integral_constant(), + std::get>(maps)); + return true; + } + return false; + }); + else + return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) { + // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways + // See https://stackoverflow.com/questions/44386415/gcc-and-clang-disagree-about-c17-constexpr-lambda-captures + constexpr auto i = ij / STRICTNESSES.size(); + constexpr auto j = ij % STRICTNESSES.size(); + if (kind == KINDS[i] && strictness == STRICTNESSES[j]) + { + if constexpr (std::is_same_v) + maps = Map(); + else + func( + std::integral_constant(), + std::integral_constant(), + std::get>(maps)); + return true; + } + return false; + }); + } + + template + bool dispatch(Func && func) const + { + return const_cast(*this).dispatch(std::forward(func)); + } private: friend class NonJoinedBlockInputStream; @@ -381,14 +457,14 @@ private: /// Substitute NULLs for non-JOINed rows. bool use_nulls; + /// Overwrite existing values when encountering the same key again + bool overwrite; + /** Blocks of "right" table. */ BlocksList blocks; - MapsAny maps_any; /// For ANY LEFT|INNER JOIN - MapsAll maps_all; /// For ALL LEFT|INNER JOIN - MapsAnyFull maps_any_full; /// For ANY RIGHT|FULL JOIN - MapsAllFull maps_all_full; /// For ALL RIGHT|FULL JOIN + std::variant maps; /// Additional data - strings for string keys and continuation elements of single-linked lists of references to rows. Arena pool; @@ -441,5 +517,28 @@ private: using JoinPtr = std::shared_ptr; using Joins = std::vector; +template +struct Join::MapGetterImpl +{ + using Map = std::conditional_t; +}; + +template +struct Join::MapGetterImpl +{ + using Map = std::conditional_t; +}; + +template <> +struct Join::MapGetterImpl +{ + using Map = MapsAll; +}; + +template <> +struct Join::MapGetterImpl +{ + using Map = MapsAllFull; +}; } diff --git a/dbms/src/Interpreters/Settings.h b/dbms/src/Interpreters/Settings.h index 646064edc86..f43776a8cf2 100644 --- a/dbms/src/Interpreters/Settings.h +++ b/dbms/src/Interpreters/Settings.h @@ -253,6 +253,7 @@ struct Settings M(SettingUInt64, max_rows_in_join, 0, "Maximum size of the hash table for JOIN (in number of rows).") \ M(SettingUInt64, max_bytes_in_join, 0, "Maximum size of the hash table for JOIN (in number of bytes in memory).") \ M(SettingOverflowMode, join_overflow_mode, OverflowMode::THROW, "What to do when the limit is exceeded.") \ + M(SettingBool, join_overwrite, false, "Whether to overwrite existing values when encountering the same key again.") \ \ M(SettingUInt64, max_rows_to_transfer, 0, "Maximum size (in rows) of the transmitted external table obtained when the GLOBAL IN/JOIN section is executed.") \ M(SettingUInt64, max_bytes_to_transfer, 0, "Maximum size (in uncompressed bytes) of the transmitted external table obtained when the GLOBAL IN/JOIN section is executed.") \ diff --git a/dbms/src/Storages/StorageJoin.cpp b/dbms/src/Storages/StorageJoin.cpp index 8d1d6d52fbf..4140570d2e6 100644 --- a/dbms/src/Storages/StorageJoin.cpp +++ b/dbms/src/Storages/StorageJoin.cpp @@ -33,7 +33,8 @@ StorageJoin::StorageJoin( SizeLimits limits_, ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_, - const ColumnsDescription & columns_) + const ColumnsDescription & columns_, + bool overwrite) : StorageSetOrJoinBase{path_, name_, columns_} , key_names(key_names_) , use_nulls(use_nulls_) @@ -45,7 +46,7 @@ StorageJoin::StorageJoin( if (!getColumns().hasPhysical(key)) throw Exception{"Key column (" + key + ") does not exist in table declaration.", ErrorCodes::NO_SUCH_COLUMN_IN_TABLE}; - join = std::make_shared(key_names, use_nulls, limits, kind, strictness); + join = std::make_shared(key_names, use_nulls, limits, kind, strictness, overwrite); join->setSampleBlock(getSampleBlock().sortColumns()); restore(); } @@ -134,6 +135,7 @@ void registerStorageJoin(StorageFactory & factory) auto max_rows_in_join = settings.max_rows_in_join; auto max_bytes_in_join = settings.max_bytes_in_join; auto join_overflow_mode = settings.join_overflow_mode; + auto join_overwrite = settings.join_overwrite; if (args.storage_def && args.storage_def->settings) { @@ -147,6 +149,8 @@ void registerStorageJoin(StorageFactory & factory) max_bytes_in_join.set(setting.value); else if (setting.name == "join_overflow_mode") join_overflow_mode.set(setting.value); + else if (setting.name == "join_overwrite") + join_overwrite.set(setting.value); else throw Exception( "Unknown setting " + setting.name + " for storage " + args.engine_name, @@ -162,7 +166,8 @@ void registerStorageJoin(StorageFactory & factory) SizeLimits{max_rows_in_join.value, max_bytes_in_join.value, join_overflow_mode.value}, kind, strictness, - args.columns); + args.columns, + join_overwrite); }); } @@ -224,12 +229,12 @@ protected: if (parent.blocks.empty()) return Block(); - if (parent.strictness == ASTTableJoin::Strictness::Any) - return createBlock(parent.maps_any); - else if (parent.strictness == ASTTableJoin::Strictness::All) - return createBlock(parent.maps_all); + Block block; + if (parent.dispatch([&](auto, auto strictness, auto & map) { block = createBlock(map); })) + ; else throw Exception("Logical error: unknown JOIN strictness (must be ANY or ALL)", ErrorCodes::LOGICAL_ERROR); + return block; } private: diff --git a/dbms/src/Storages/StorageJoin.h b/dbms/src/Storages/StorageJoin.h index ebe9dc68ce4..177cdee9834 100644 --- a/dbms/src/Storages/StorageJoin.h +++ b/dbms/src/Storages/StorageJoin.h @@ -62,7 +62,8 @@ protected: bool use_nulls_, SizeLimits limits_, ASTTableJoin::Kind kind_, ASTTableJoin::Strictness strictness_, - const ColumnsDescription & columns_); + const ColumnsDescription & columns_, + bool overwrite); }; } diff --git a/dbms/tests/queries/0_stateless/00830_join_overwrite.reference b/dbms/tests/queries/0_stateless/00830_join_overwrite.reference new file mode 100644 index 00000000000..4792e70f333 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00830_join_overwrite.reference @@ -0,0 +1,2 @@ +2 +3 diff --git a/dbms/tests/queries/0_stateless/00830_join_overwrite.sql b/dbms/tests/queries/0_stateless/00830_join_overwrite.sql new file mode 100644 index 00000000000..1f981eb00bd --- /dev/null +++ b/dbms/tests/queries/0_stateless/00830_join_overwrite.sql @@ -0,0 +1,15 @@ +USE test; + +DROP TABLE IF EXISTS kv; + +CREATE TABLE kv (k UInt32, v UInt32) ENGINE Join(Any, Left, k); +INSERT INTO kv VALUES (1, 2); +INSERT INTO kv VALUES (1, 3); +SELECT joinGet('kv', 'v', toUInt32(1)); +CREATE TABLE kv_overwrite (k UInt32, v UInt32) ENGINE Join(Any, Left, k) SETTINGS join_overwrite = 1; +INSERT INTO kv_overwrite VALUES (1, 2); +INSERT INTO kv_overwrite VALUES (1, 3); +SELECT joinGet('kv_overwrite', 'v', toUInt32(1)); + +DROP TABLE kv; +DROP TABLE kv_overwrite; diff --git a/libs/libcommon/CMakeLists.txt b/libs/libcommon/CMakeLists.txt index 5c6c242407f..0caa57453c9 100644 --- a/libs/libcommon/CMakeLists.txt +++ b/libs/libcommon/CMakeLists.txt @@ -42,6 +42,7 @@ add_library (common ${LINK_MODE} include/common/demangle.h include/common/SetTerminalEcho.h include/common/find_symbols.h + include/common/constexpr_helpers.h include/ext/bit_cast.h include/ext/collection_cast.h diff --git a/libs/libcommon/include/common/constexpr_helpers.h b/libs/libcommon/include/common/constexpr_helpers.h new file mode 100644 index 00000000000..c6fcb0bb4db --- /dev/null +++ b/libs/libcommon/include/common/constexpr_helpers.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +template +inline constexpr bool static_in_v = std::disjunction_v...>; + +template +bool func_wrapper(Func && func, Arg && arg) +{ + if constexpr (std::is_void_v>) + { + func(arg); + return false; + } + else + return func(arg); +} + +template +constexpr bool static_for_impl(Func && f, std::integer_sequence) +{ + return (func_wrapper(std::forward(f), std::integral_constant{}) || ...); +} + +template +constexpr bool static_for(Func && f) +{ + using T = decltype(Begin); + return static_for_impl(std::forward(f), std::make_integer_sequence{}); +} From 8a401e491a5806c5ff3ba9049ad299b4d0bdcb49 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Tue, 15 Jan 2019 00:40:02 +0300 Subject: [PATCH 2/4] Update Join.cpp --- dbms/src/Interpreters/Join.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dbms/src/Interpreters/Join.cpp b/dbms/src/Interpreters/Join.cpp index da8209a09d3..0571723646f 100644 --- a/dbms/src/Interpreters/Join.cpp +++ b/dbms/src/Interpreters/Join.cpp @@ -468,7 +468,8 @@ bool Join::insertFromBlock(const Block & block) if (kind != ASTTableJoin::Kind::Cross) { - dispatch([&](auto, auto strictness_, auto & map) { + dispatch([&](auto, auto strictness_, auto & map) + { insertFromBlockImpl(type, map, rows, key_columns, keys_size, key_sizes, stored_block, null_map, pool); }); } @@ -919,10 +920,13 @@ void Join::joinBlock(Block & block, const Names & key_names_left, const NameSet checkTypesOfKeys(block, key_names_left, sample_block_with_keys); - if (dispatch([&](auto kind_, auto strictness_, auto & map) { + if (dispatch([&](auto kind_, auto strictness_, auto & map) + { joinBlockImpl(block, key_names_left, needed_key_names_right, sample_block_with_columns_to_add, map); })) - ; + { + /// Joined + } else if (kind == ASTTableJoin::Kind::Cross) joinBlockImplCross(block); else From 64c31a6ad7fed521089da9c234180b602c8f1c4c Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Tue, 15 Jan 2019 00:40:42 +0300 Subject: [PATCH 3/4] Update Join.h --- dbms/src/Interpreters/Join.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dbms/src/Interpreters/Join.h b/dbms/src/Interpreters/Join.h index c1f665262a8..38b05fb2de1 100644 --- a/dbms/src/Interpreters/Join.h +++ b/dbms/src/Interpreters/Join.h @@ -403,7 +403,8 @@ public: bool dispatch(Func && func) { if (overwrite) - return static_for<0, KINDS.size()>([&](auto i) { + return static_for<0, KINDS.size()>([&](auto i) + { if (kind == KINDS[i] && strictness == ASTTableJoin::Strictness::Any) { if constexpr (std::is_same_v) @@ -418,7 +419,8 @@ public: return false; }); else - return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) { + return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) + { // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways // See https://stackoverflow.com/questions/44386415/gcc-and-clang-disagree-about-c17-constexpr-lambda-captures constexpr auto i = ij / STRICTNESSES.size(); From 27a0c37d7773d4392065cb45a72c8681d65847b9 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Tue, 15 Jan 2019 00:41:35 +0300 Subject: [PATCH 4/4] Update Join.h --- dbms/src/Interpreters/Join.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dbms/src/Interpreters/Join.h b/dbms/src/Interpreters/Join.h index 38b05fb2de1..43de3092409 100644 --- a/dbms/src/Interpreters/Join.h +++ b/dbms/src/Interpreters/Join.h @@ -403,6 +403,7 @@ public: bool dispatch(Func && func) { if (overwrite) + { return static_for<0, KINDS.size()>([&](auto i) { if (kind == KINDS[i] && strictness == ASTTableJoin::Strictness::Any) @@ -418,7 +419,9 @@ public: } return false; }); + } else + { return static_for<0, KINDS.size() * STRICTNESSES.size()>([&](auto ij) { // NOTE: Avoid using nested static loop as GCC and CLANG have bugs in different ways @@ -438,6 +441,7 @@ public: } return false; }); + } } template