1 | #pragma once |
2 | |
3 | #include <Columns/IColumn.h> |
4 | |
5 | |
6 | namespace DB |
7 | { |
8 | |
9 | /** Allows to access internal array of ColumnVector or ColumnFixedString without cast to concrete type. |
10 | * We will inherit ColumnVector and ColumnFixedString from this class instead of IColumn. |
11 | * Assumes data layout of ColumnVector, ColumnFixedString and PODArray. |
12 | * |
13 | * Why it is needed? |
14 | * |
15 | * There are some algorithms that specialize on the size of data type but doesn't care about concrete type. |
16 | * The same specialization may work for UInt64, Int64, Float64, FixedString(8), if it only does byte moving and hashing. |
17 | * To avoid code bloat and compile time increase, we can use single template instantiation for these cases |
18 | * and just static_cast pointer to some single column type (e. g. ColumnUInt64) assuming that all types have identical memory layout. |
19 | * |
20 | * But this static_cast (downcast to unrelated type) is illegal according to the C++ standard and UBSan warns about it. |
21 | * To allow functional tests to work under UBSan we have to separate some base class that will present the memory layout in explicit way, |
22 | * and we will do static_cast to this class. |
23 | */ |
24 | class ColumnVectorHelper : public IColumn |
25 | { |
26 | public: |
27 | template <size_t ELEMENT_SIZE> |
28 | const char * getRawDataBegin() const |
29 | { |
30 | return reinterpret_cast<const PODArrayBase<ELEMENT_SIZE, 4096, Allocator<false>, 15, 16> *>(reinterpret_cast<const char *>(this) + sizeof(*this))->raw_data(); |
31 | } |
32 | |
33 | template <size_t ELEMENT_SIZE> |
34 | void insertRawData(const char * ptr) |
35 | { |
36 | return reinterpret_cast<PODArrayBase<ELEMENT_SIZE, 4096, Allocator<false>, 15, 16> *>(reinterpret_cast<char *>(this) + sizeof(*this))->push_back_raw(ptr); |
37 | } |
38 | }; |
39 | |
40 | } |
41 | |