From de524a0158c8a61c2d9a02273ad77bdbc0925471 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Tue, 4 Dec 2018 13:27:44 +0300 Subject: [PATCH] Fix merging aggregate data for NULL key. --- dbms/src/Interpreters/Aggregator.cpp | 46 ++++++++++++++++++++++++++++ dbms/src/Interpreters/Aggregator.h | 7 +++++ 2 files changed, 53 insertions(+) diff --git a/dbms/src/Interpreters/Aggregator.cpp b/dbms/src/Interpreters/Aggregator.cpp index e2cbc982897..2745cfc0233 100644 --- a/dbms/src/Interpreters/Aggregator.cpp +++ b/dbms/src/Interpreters/Aggregator.cpp @@ -1513,12 +1513,50 @@ BlocksList Aggregator::convertToBlocks(AggregatedDataVariants & data_variants, b } +template +void NO_INLINE Aggregator::mergeDataNullKey( + Table & table_dst, + Table & table_src, + Arena * arena) const +{ + if constexpr (Method::low_cardinality_optimization) + { + if (table_src.hasNullKeyData()) + { + if (!table_dst.hasNullKeyData()) + { + table_dst.hasNullKeyData() = true; + table_dst.getNullKeyData() = table_src.getNullKeyData(); + } + else + { + for (size_t i = 0; i < params.aggregates_size; ++i) + aggregate_functions[i]->merge( + table_dst.getNullKeyData() + offsets_of_aggregate_states[i], + table_src.getNullKeyData() + offsets_of_aggregate_states[i], + arena); + + for (size_t i = 0; i < params.aggregates_size; ++i) + aggregate_functions[i]->destroy( + table_src.getNullKeyData() + offsets_of_aggregate_states[i]); + } + + table_src.hasNullKeyData() = false; + table_src.getNullKeyData() = nullptr; + } + } +} + + template void NO_INLINE Aggregator::mergeDataImpl( Table & table_dst, Table & table_src, Arena * arena) const { + if constexpr (Method::low_cardinality_optimization) + mergeDataNullKey(table_dst, table_src, arena); + for (auto it = table_src.begin(), end = table_src.end(); it != end; ++it) { typename Table::iterator res_it; @@ -1556,6 +1594,10 @@ void NO_INLINE Aggregator::mergeDataNoMoreKeysImpl( Table & table_src, Arena * arena) const { + /// Note : will create data for NULL key if not exist + if constexpr (Method::low_cardinality_optimization) + mergeDataNullKey(table_dst, table_src, arena); + for (auto it = table_src.begin(), end = table_src.end(); it != end; ++it) { typename Table::iterator res_it = table_dst.find(it->first, it.getHash()); @@ -1586,6 +1628,10 @@ void NO_INLINE Aggregator::mergeDataOnlyExistingKeysImpl( Table & table_src, Arena * arena) const { + /// Note : will create data for NULL key if not exist + if constexpr (Method::low_cardinality_optimization) + mergeDataNullKey(table_dst, table_src, arena); + for (auto it = table_src.begin(); it != table_src.end(); ++it) { decltype(it) res_it = table_dst.find(it->first, it.getHash()); diff --git a/dbms/src/Interpreters/Aggregator.h b/dbms/src/Interpreters/Aggregator.h index 4b1b2012722..6432126a58e 100644 --- a/dbms/src/Interpreters/Aggregator.h +++ b/dbms/src/Interpreters/Aggregator.h @@ -1652,6 +1652,13 @@ public: Arena * arena) const; protected: + /// Merge NULL key data from hash table `src` into `dst`. + template + void mergeDataNullKey( + Table & table_dst, + Table & table_src, + Arena * arena) const; + /// Merge data from hash table `src` into `dst`. template void mergeDataImpl(