1 | #pragma once |
2 | |
3 | #include <Core/Field.h> |
4 | #include <Common/Exception.h> |
5 | #include <Columns/IColumn.h> |
6 | #include <Common/typeid_cast.h> |
7 | #include <Common/assert_cast.h> |
8 | |
9 | |
10 | namespace DB |
11 | { |
12 | |
13 | namespace ErrorCodes |
14 | { |
15 | extern const int NOT_IMPLEMENTED; |
16 | } |
17 | |
18 | |
19 | /** ColumnConst contains another column with single element, |
20 | * but looks like a column with arbitrary amount of same elements. |
21 | */ |
22 | class ColumnConst final : public COWHelper<IColumn, ColumnConst> |
23 | { |
24 | private: |
25 | friend class COWHelper<IColumn, ColumnConst>; |
26 | |
27 | WrappedPtr data; |
28 | size_t s; |
29 | |
30 | ColumnConst(const ColumnPtr & data, size_t s_); |
31 | ColumnConst(const ColumnConst & src) = default; |
32 | |
33 | public: |
34 | ColumnPtr convertToFullColumn() const; |
35 | |
36 | ColumnPtr convertToFullColumnIfConst() const override |
37 | { |
38 | return convertToFullColumn(); |
39 | } |
40 | |
41 | ColumnPtr removeLowCardinality() const; |
42 | |
43 | std::string getName() const override |
44 | { |
45 | return "Const(" + data->getName() + ")" ; |
46 | } |
47 | |
48 | const char * getFamilyName() const override |
49 | { |
50 | return "Const" ; |
51 | } |
52 | |
53 | MutableColumnPtr cloneResized(size_t new_size) const override |
54 | { |
55 | return ColumnConst::create(data, new_size); |
56 | } |
57 | |
58 | size_t size() const override |
59 | { |
60 | return s; |
61 | } |
62 | |
63 | Field operator[](size_t) const override |
64 | { |
65 | return (*data)[0]; |
66 | } |
67 | |
68 | void get(size_t, Field & res) const override |
69 | { |
70 | data->get(0, res); |
71 | } |
72 | |
73 | StringRef getDataAt(size_t) const override |
74 | { |
75 | return data->getDataAt(0); |
76 | } |
77 | |
78 | StringRef getDataAtWithTerminatingZero(size_t) const override |
79 | { |
80 | return data->getDataAtWithTerminatingZero(0); |
81 | } |
82 | |
83 | UInt64 get64(size_t) const override |
84 | { |
85 | return data->get64(0); |
86 | } |
87 | |
88 | UInt64 getUInt(size_t) const override |
89 | { |
90 | return data->getUInt(0); |
91 | } |
92 | |
93 | Int64 getInt(size_t) const override |
94 | { |
95 | return data->getInt(0); |
96 | } |
97 | |
98 | bool getBool(size_t) const override |
99 | { |
100 | return data->getBool(0); |
101 | } |
102 | |
103 | Float64 getFloat64(size_t) const override |
104 | { |
105 | return data->getFloat64(0); |
106 | } |
107 | |
108 | Float32 getFloat32(size_t) const override |
109 | { |
110 | return data->getFloat32(0); |
111 | } |
112 | |
113 | bool isNullAt(size_t) const override |
114 | { |
115 | return data->isNullAt(0); |
116 | } |
117 | |
118 | void insertRangeFrom(const IColumn &, size_t /*start*/, size_t length) override |
119 | { |
120 | s += length; |
121 | } |
122 | |
123 | void insert(const Field &) override |
124 | { |
125 | ++s; |
126 | } |
127 | |
128 | void insertData(const char *, size_t) override |
129 | { |
130 | ++s; |
131 | } |
132 | |
133 | void insertFrom(const IColumn &, size_t) override |
134 | { |
135 | ++s; |
136 | } |
137 | |
138 | void insertDefault() override |
139 | { |
140 | ++s; |
141 | } |
142 | |
143 | void popBack(size_t n) override |
144 | { |
145 | s -= n; |
146 | } |
147 | |
148 | StringRef serializeValueIntoArena(size_t, Arena & arena, char const *& begin) const override |
149 | { |
150 | return data->serializeValueIntoArena(0, arena, begin); |
151 | } |
152 | |
153 | const char * deserializeAndInsertFromArena(const char * pos) override |
154 | { |
155 | auto res = data->deserializeAndInsertFromArena(pos); |
156 | data->popBack(1); |
157 | ++s; |
158 | return res; |
159 | } |
160 | |
161 | void updateHashWithValue(size_t, SipHash & hash) const override |
162 | { |
163 | data->updateHashWithValue(0, hash); |
164 | } |
165 | |
166 | ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override; |
167 | ColumnPtr replicate(const Offsets & offsets) const override; |
168 | ColumnPtr permute(const Permutation & perm, size_t limit) const override; |
169 | ColumnPtr index(const IColumn & indexes, size_t limit) const override; |
170 | void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override; |
171 | |
172 | size_t byteSize() const override |
173 | { |
174 | return data->byteSize() + sizeof(s); |
175 | } |
176 | |
177 | size_t allocatedBytes() const override |
178 | { |
179 | return data->allocatedBytes() + sizeof(s); |
180 | } |
181 | |
182 | int compareAt(size_t, size_t, const IColumn & rhs, int nan_direction_hint) const override |
183 | { |
184 | return data->compareAt(0, 0, *assert_cast<const ColumnConst &>(rhs).data, nan_direction_hint); |
185 | } |
186 | |
187 | MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override; |
188 | |
189 | void gather(ColumnGathererStream &) override |
190 | { |
191 | throw Exception("Cannot gather into constant column " + getName(), ErrorCodes::NOT_IMPLEMENTED); |
192 | } |
193 | |
194 | void getExtremes(Field & min, Field & max) const override |
195 | { |
196 | data->getExtremes(min, max); |
197 | } |
198 | |
199 | void forEachSubcolumn(ColumnCallback callback) override |
200 | { |
201 | callback(data); |
202 | } |
203 | |
204 | bool structureEquals(const IColumn & rhs) const override |
205 | { |
206 | if (auto rhs_concrete = typeid_cast<const ColumnConst *>(&rhs)) |
207 | return data->structureEquals(*rhs_concrete->data); |
208 | return false; |
209 | } |
210 | |
211 | bool isNullable() const override { return isColumnNullable(*data); } |
212 | bool onlyNull() const override { return data->isNullAt(0); } |
213 | bool isNumeric() const override { return data->isNumeric(); } |
214 | bool isFixedAndContiguous() const override { return data->isFixedAndContiguous(); } |
215 | bool valuesHaveFixedSize() const override { return data->valuesHaveFixedSize(); } |
216 | size_t sizeOfValueIfFixed() const override { return data->sizeOfValueIfFixed(); } |
217 | StringRef getRawData() const override { return data->getRawData(); } |
218 | |
219 | /// Not part of the common interface. |
220 | |
221 | IColumn & getDataColumn() { return *data; } |
222 | const IColumn & getDataColumn() const { return *data; } |
223 | const ColumnPtr & getDataColumnPtr() const { return data; } |
224 | |
225 | Field getField() const { return getDataColumn()[0]; } |
226 | |
227 | /// The constant value. It is valid even if the size of the column is 0. |
228 | template <typename T> |
229 | T getValue() const { return getField().safeGet<NearestFieldType<T>>(); } |
230 | }; |
231 | |
232 | } |
233 | |