Overcome gcc limitation

This commit is contained in:
Alexey Milovidov 2021-05-08 03:29:51 +03:00
parent e8c29bf15f
commit 06e79e914c

View File

@ -1,5 +1,7 @@
#pragma once
#include <common/unaligned.h>
#include <Common/typeid_cast.h>
#include <Common/assert_cast.h>
@ -34,7 +36,7 @@ namespace DB
*/
template <typename T>
struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
struct AggregateFunctionUniqUpToData
{
/** If count == threshold + 1 - this means that it is "overflowed" (values greater than threshold).
* In this case (for example, after calling the merge function), the `data` array does not necessarily contain the initialized values
@ -42,7 +44,17 @@ struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
* then set count to `threshold + 1`, and values from another state are not copied.
*/
UInt8 count = 0;
T data[0];
char data_ptr[0];
T load(size_t i) const
{
return unalignedLoad<T>(data_ptr + i * sizeof(T));
}
void store(size_t i, const T & x)
{
unalignedStore<T>(data_ptr + i * sizeof(T), x);
}
size_t size() const
{
@ -59,12 +71,12 @@ struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
/// Linear search for the matching element.
for (size_t i = 0; i < count; ++i)
if (data[i] == x)
if (load(i) == x)
return;
/// Did not find the matching element. If there is room for one more element, insert it.
if (count < threshold)
data[count] = x;
store(count, x);
/// After increasing count, the state may be overflowed.
++count;
@ -83,7 +95,7 @@ struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
}
for (size_t i = 0; i < rhs.count; ++i)
insert(rhs.data[i], threshold);
insert(rhs.load(i), threshold);
}
void write(WriteBuffer & wb, UInt8 threshold) const
@ -92,7 +104,7 @@ struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
/// Write values only if the state is not overflowed. Otherwise, they are not needed, and only the fact that the state is overflowed is important.
if (count <= threshold)
wb.write(reinterpret_cast<const char *>(data), count * sizeof(data[0]));
wb.write(data_ptr, count * sizeof(T));
}
void read(ReadBuffer & rb, UInt8 threshold)
@ -100,7 +112,7 @@ struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
readBinary(count, rb);
if (count <= threshold)
rb.read(reinterpret_cast<char *>(data), count * sizeof(data[0]));
rb.read(data_ptr, count * sizeof(T));
}
/// ALWAYS_INLINE is required to have better code layout for uniqUpTo function