1 | #pragma once |
2 | |
3 | #include <Common/PODArray.h> |
4 | #include <Common/memcmpSmall.h> |
5 | #include <Common/typeid_cast.h> |
6 | #include <Common/assert_cast.h> |
7 | #include <Columns/IColumn.h> |
8 | #include <Columns/IColumnImpl.h> |
9 | #include <Columns/ColumnVectorHelper.h> |
10 | #include <Core/Field.h> |
11 | |
12 | |
13 | namespace DB |
14 | { |
15 | |
16 | /** A column of values of "fixed-length string" type. |
17 | * If you insert a smaller string, it will be padded with zero bytes. |
18 | */ |
19 | class ColumnFixedString final : public COWHelper<ColumnVectorHelper, ColumnFixedString> |
20 | { |
21 | public: |
22 | friend class COWHelper<ColumnVectorHelper, ColumnFixedString>; |
23 | |
24 | using Chars = PaddedPODArray<UInt8>; |
25 | |
26 | private: |
27 | /// Bytes of rows, laid in succession. The strings are stored without a trailing zero byte. |
28 | /** NOTE It is required that the offset and type of chars in the object be the same as that of `data in ColumnUInt8`. |
29 | * Used in `packFixed` function (AggregationCommon.h) |
30 | */ |
31 | Chars chars; |
32 | /// The size of the rows. |
33 | const size_t n; |
34 | |
35 | template <bool positive> |
36 | struct less; |
37 | |
38 | /** Create an empty column of strings of fixed-length `n` */ |
39 | ColumnFixedString(size_t n_) : n(n_) {} |
40 | |
41 | ColumnFixedString(const ColumnFixedString & src) : chars(src.chars.begin(), src.chars.end()), n(src.n) {} |
42 | |
43 | public: |
44 | std::string getName() const override { return "FixedString(" + std::to_string(n) + ")" ; } |
45 | const char * getFamilyName() const override { return "FixedString" ; } |
46 | |
47 | MutableColumnPtr cloneResized(size_t size) const override; |
48 | |
49 | size_t size() const override |
50 | { |
51 | return chars.size() / n; |
52 | } |
53 | |
54 | size_t byteSize() const override |
55 | { |
56 | return chars.size() + sizeof(n); |
57 | } |
58 | |
59 | size_t allocatedBytes() const override |
60 | { |
61 | return chars.allocated_bytes() + sizeof(n); |
62 | } |
63 | |
64 | void protect() override |
65 | { |
66 | chars.protect(); |
67 | } |
68 | |
69 | Field operator[](size_t index) const override |
70 | { |
71 | return String(reinterpret_cast<const char *>(&chars[n * index]), n); |
72 | } |
73 | |
74 | void get(size_t index, Field & res) const override |
75 | { |
76 | res.assignString(reinterpret_cast<const char *>(&chars[n * index]), n); |
77 | } |
78 | |
79 | StringRef getDataAt(size_t index) const override |
80 | { |
81 | return StringRef(&chars[n * index], n); |
82 | } |
83 | |
84 | void insert(const Field & x) override; |
85 | |
86 | void insertFrom(const IColumn & src_, size_t index) override; |
87 | |
88 | void insertData(const char * pos, size_t length) override; |
89 | |
90 | void insertDefault() override |
91 | { |
92 | chars.resize_fill(chars.size() + n); |
93 | } |
94 | |
95 | virtual void insertManyDefaults(size_t length) override |
96 | { |
97 | chars.resize_fill(chars.size() + n * length); |
98 | } |
99 | |
100 | void popBack(size_t elems) override |
101 | { |
102 | chars.resize_assume_reserved(chars.size() - n * elems); |
103 | } |
104 | |
105 | StringRef serializeValueIntoArena(size_t index, Arena & arena, char const *& begin) const override; |
106 | |
107 | const char * deserializeAndInsertFromArena(const char * pos) override; |
108 | |
109 | void updateHashWithValue(size_t index, SipHash & hash) const override; |
110 | |
111 | int compareAt(size_t p1, size_t p2, const IColumn & rhs_, int /*nan_direction_hint*/) const override |
112 | { |
113 | const ColumnFixedString & rhs = assert_cast<const ColumnFixedString &>(rhs_); |
114 | return memcmpSmallAllowOverflow15(chars.data() + p1 * n, rhs.chars.data() + p2 * n, n); |
115 | } |
116 | |
117 | void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override; |
118 | |
119 | void insertRangeFrom(const IColumn & src, size_t start, size_t length) override; |
120 | |
121 | ColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override; |
122 | |
123 | ColumnPtr permute(const Permutation & perm, size_t limit) const override; |
124 | |
125 | ColumnPtr index(const IColumn & indexes, size_t limit) const override; |
126 | |
127 | template <typename Type> |
128 | ColumnPtr indexImpl(const PaddedPODArray<Type> & indexes, size_t limit) const; |
129 | |
130 | ColumnPtr replicate(const Offsets & offsets) const override; |
131 | |
132 | MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override |
133 | { |
134 | return scatterImpl<ColumnFixedString>(num_columns, selector); |
135 | } |
136 | |
137 | void gather(ColumnGathererStream & gatherer_stream) override; |
138 | |
139 | void reserve(size_t size) override |
140 | { |
141 | chars.reserve(n * size); |
142 | } |
143 | |
144 | void getExtremes(Field & min, Field & max) const override; |
145 | |
146 | bool structureEquals(const IColumn & rhs) const override |
147 | { |
148 | if (auto rhs_concrete = typeid_cast<const ColumnFixedString *>(&rhs)) |
149 | return n == rhs_concrete->n; |
150 | return false; |
151 | } |
152 | |
153 | bool canBeInsideNullable() const override { return true; } |
154 | |
155 | bool isFixedAndContiguous() const override { return true; } |
156 | size_t sizeOfValueIfFixed() const override { return n; } |
157 | StringRef getRawData() const override { return StringRef(chars.data(), chars.size()); } |
158 | |
159 | /// Specialized part of interface, not from IColumn. |
160 | void insertString(const String & string) { insertData(string.c_str(), string.size()); } |
161 | Chars & getChars() { return chars; } |
162 | const Chars & getChars() const { return chars; } |
163 | |
164 | size_t getN() const { return n; } |
165 | }; |
166 | |
167 | |
168 | } |
169 | |